From bedd07ed2a35ff79a92a8292c84969c58dc39ab9 Mon Sep 17 00:00:00 2001 From: alexcos20 Date: Fri, 11 Sep 2020 05:58:42 -0700 Subject: [PATCH] search for previous valid orders --- src/datatokens/Datatokens.ts | 54 ++++++++++++++++++++++-- src/ocean/Assets.ts | 29 +++++++------ src/utils/ConversionTypeHelpers.ts | 1 + test/integration/Marketplaceflow.test.ts | 16 +++++++ 4 files changed, 85 insertions(+), 15 deletions(-) diff --git a/src/datatokens/Datatokens.ts b/src/datatokens/Datatokens.ts index 0f4cd537..312760bd 100644 --- a/src/datatokens/Datatokens.ts +++ b/src/datatokens/Datatokens.ts @@ -6,6 +6,8 @@ import defaultDatatokensABI from '@oceanprotocol/contracts/artifacts/DataTokenTe import wordListDefault from '../data/words.json' import { TransactionReceipt } from 'web3-core' +import { time } from 'console' +import BigNumber from 'bignumber.js' /** * Provides a interface to DataTokens */ @@ -384,7 +386,7 @@ export class DataTokens { * @param {Number} serviceId * @param {String} mpFeeAddress * @param {String} mpFeePercentage - * @param {String} address + * @param {String} address consumer Address * @return {Promise} string */ public async startOrder( @@ -405,16 +407,62 @@ export class DataTokens { .startOrder( providerAddress, this.web3.utils.toWei(amount), - String(did), + did, String(serviceId), mpFeeAddress, this.web3.utils.toWei(mpFeePercentage) ) - .send({ from: address }) + .send({ from: address, gas: 600000 }) return trxReceipt } catch (e) { console.error(e) return null } } + + /** Search and return txid for a previous valid order with the same params + * @param {String} dataTokenAddress + * @param {String} providerAddress + * @param {String} amount + * @param {String} did + * @param {Number} serviceId + * @param {Number} timeout service timeout + * @param {String} address consumer Address + * @return {Promise} string + */ + public async getPreviousValidOrders( + dataTokenAddress: string, + providerAddress: string, + amount: string, + did: string, + serviceId: number, + timeout: number, + address: string + ): Promise { + const datatoken = new this.web3.eth.Contract(this.datatokensABI, dataTokenAddress, { + from: address + }) + const events = await datatoken.getPastEvents('OrderStarted', { + fromBlock: 0, + toBlock: 'latest' + }) + for (let i = 0; i < events.length; i++) { + if ( + events[i].returnValues.did === did && + String(events[i].returnValues.amount) === String(amount) && + events[i].returnValues.receiver === providerAddress && + String(events[i].returnValues.serviceId) === String(serviceId) + ) { + const transaction = await this.web3.eth.getTransaction(events[i].transactionHash) + if (transaction.from === address) { + if (timeout === 0) return events[i].transactionHash + const blockDetails = await this.web3.eth.getBlock(events[i].blockHash) + const expiry = new BigNumber(blockDetails.timestamp).plus(timeout) + const unixTime = new BigNumber(Math.floor(Date.now() / 1000)) + if (unixTime.isLessThan(expiry)) return events[i].transactionHash + } + } + } + return null + } } diff --git a/src/ocean/Assets.ts b/src/ocean/Assets.ts index 623796d0..50404c75 100644 --- a/src/ocean/Assets.ts +++ b/src/ocean/Assets.ts @@ -477,25 +477,30 @@ export class Assets extends Instantiable { mpFeePercent ) if (!providerData) return null + const service = await this.getServiceByIndex(did, serviceIndex) + const previousOrder = await datatokens.getPreviousValidOrders( + providerData.dataToken, + providerData.to, + providerData.numTokens, + didZeroX(did), + serviceIndex, + service.attributes.main.timeout, + consumerAddress + ) + if (previousOrder) return previousOrder const balance = new BigNumber( await datatokens.balance(providerData.dataToken, consumerAddress) ) const totalCost = new BigNumber(providerData.totalCost) if (balance.isLessThanOrEqualTo(totalCost)) { - console.error('Not enough funds') - + console.error( + 'Not enough funds. Needed ' + + totalCost.toString() + + ' but balance is ' + + balance.toString() + ) return null } - console.log( - 'Balance:' + - balance.toString() + - '| dtCost:' + - providerData.dtCost.toString() + - '|Fees:' + - providerData.totalFee.toString() + - '|Total:' + - providerData.totalCost.toString() - ) const txid = await datatokens.startOrder( providerData.dataToken, providerData.to, diff --git a/src/utils/ConversionTypeHelpers.ts b/src/utils/ConversionTypeHelpers.ts index 331578d7..52015021 100644 --- a/src/utils/ConversionTypeHelpers.ts +++ b/src/utils/ConversionTypeHelpers.ts @@ -22,6 +22,7 @@ export function didTransformer(input = '', prefixOutput: boolean): string { // 0x + did:op: transformer export const didZeroX = (input: string): string => zeroX(didTransformer(input, false)) +export const didNoZeroX = (input: string): string => noZeroX(didTransformer(input, false)) // Shared functions function inputMatch( diff --git a/test/integration/Marketplaceflow.test.ts b/test/integration/Marketplaceflow.test.ts index c0ad435e..a998b743 100644 --- a/test/integration/Marketplaceflow.test.ts +++ b/test/integration/Marketplaceflow.test.ts @@ -170,6 +170,22 @@ describe('Marketplace flow', () => { ) }) }) + + it('Bob consumes same asset again, without paying', async () => { + const balanceBefore = await datatoken.balance(tokenAddress, bob.getId()) + await ocean.assets.order(ddo.id, accessService.type, bob.getId()).then(async (tx) => { + assert(tx != null) + await ocean.assets.download( + ddo.id, + tx, + tokenAddress, + bob, + './node_modules/my-datasets' + ) + }) + const balanceAfter = await datatoken.balance(tokenAddress, bob.getId()) + assert(balanceBefore === balanceAfter) + }) it('owner can list there assets', async () => { const assets = await ocean.assets.ownerAssets(alice.getId()) assert(assets.length > 0)