diff --git a/package-lock.json b/package-lock.json index 09214c61..6680fe43 100644 --- a/package-lock.json +++ b/package-lock.json @@ -927,9 +927,9 @@ } }, "@oceanprotocol/contracts": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@oceanprotocol/contracts/-/contracts-0.3.5.tgz", - "integrity": "sha512-z7ziNbRwsPrJi+zGyokgUEKivD90a5/9jjV+WLj1q5U96g60rd5rxox4EKNPNGlHx/m5rWBJhHBV4rseJjtFjg==" + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@oceanprotocol/contracts/-/contracts-0.4.1.tgz", + "integrity": "sha512-gc6bCt3pq9cpk1mYDKfsZhLlaM+8yQDFmOjtmT1KGXRmnTBcvmwCQXMrL5VohFaFi7Iqio3FZtuhYyRaEjikCw==" }, "@octokit/auth-token": { "version": "2.4.2", diff --git a/package.json b/package.json index f348e1cb..9e18a4cc 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ }, "dependencies": { "@ethereum-navigator/navigator": "^0.5.0", - "@oceanprotocol/contracts": "^0.3.5", + "@oceanprotocol/contracts": "^0.4.1", "decimal.js": "^10.2.0", "fs": "0.0.1-security", "node-fetch": "^2.6.0", diff --git a/src/balancer/OceanPool.ts b/src/balancer/OceanPool.ts index 8e08d4fc..804b1be5 100644 --- a/src/balancer/OceanPool.ts +++ b/src/balancer/OceanPool.ts @@ -333,7 +333,7 @@ export class OceanPool extends Pool { const factory = new this.web3.eth.Contract(this.factoryABI, this.factoryAddress, { from: account }) - const events = await factory.getPastEvents('SPoolRegistered', { + const events = await factory.getPastEvents('BPoolRegistered', { filter: {}, fromBlock: 0, toBlock: 'latest' diff --git a/src/balancer/Pool.ts b/src/balancer/Pool.ts index 51fdf8a3..c2a4d9ba 100644 --- a/src/balancer/Pool.ts +++ b/src/balancer/Pool.ts @@ -2,7 +2,7 @@ import Web3 from 'web3' import { AbiItem } from 'web3-utils/types' import { TransactionReceipt } from 'web3-core' import Decimal from 'decimal.js' -import jsonpoolABI from '@oceanprotocol/contracts/artifacts/SPool.json' +import jsonpoolABI from '@oceanprotocol/contracts/artifacts/BPool.json' import { PoolFactory } from './PoolFactory' /** diff --git a/src/balancer/PoolFactory.ts b/src/balancer/PoolFactory.ts index c7c77c70..bf363bc1 100644 --- a/src/balancer/PoolFactory.ts +++ b/src/balancer/PoolFactory.ts @@ -1,6 +1,6 @@ import Web3 from 'web3' import { AbiItem } from 'web3-utils/types' -import jsonFactoryABI from '@oceanprotocol/contracts/artifacts/SFactory.json' +import jsonFactoryABI from '@oceanprotocol/contracts/artifacts/BFactory.json' export class PoolFactory { public GASLIMIT_DEFAULT = 5000000 @@ -43,13 +43,13 @@ export class PoolFactory { }) const transactiondata = await factory.methods - .newSPool() + .newBPool() .send({ from: account, gas: this.GASLIMIT_DEFAULT }) let pooladdress: string try { - pooladdress = transactiondata.events.SPoolRegistered.returnValues[0] + pooladdress = transactiondata.events.BPoolRegistered.returnValues[0] } catch (e) { console.error(e) } diff --git a/src/datatokens/Datatokens.ts b/src/datatokens/Datatokens.ts index 719f6cbc..b033c95e 100644 --- a/src/datatokens/Datatokens.ts +++ b/src/datatokens/Datatokens.ts @@ -35,26 +35,37 @@ export class DataTokens { /** * Create new datatoken * @param {String} metaDataStoreURI + * @param {String} name Token name + * @param {String} symbol Token symbol + * @param {String} cap Maximum cap (Number) - will be converted to wei * @param {String} address * @return {Promise} datatoken address */ - public async create(metaDataStoreURI: string, address: string): Promise { + public async create( + metaDataStoreURI: string, + name: string, + symbol: string, + cap: string, + address: string + ): Promise { // Create factory contract object const factory = new this.web3.eth.Contract(this.factoryABI, this.factoryAddress, { from: address }) const estGas = await factory.methods - .createToken(metaDataStoreURI) + .createToken(metaDataStoreURI, name, symbol, this.web3.utils.toWei(cap)) .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' - }) + const trxReceipt = await factory.methods + .createToken(metaDataStoreURI, name, symbol, this.web3.utils.toWei(cap)) + .send({ + from: address, + gas: estGas + 1, + gasPrice: '3000000000' + }) let tokenAddress = null try { diff --git a/src/exchange/FixedRateExchange.ts b/src/exchange/FixedRateExchange.ts new file mode 100644 index 00000000..fde5f405 --- /dev/null +++ b/src/exchange/FixedRateExchange.ts @@ -0,0 +1,346 @@ +import defaultFixedRateExchangeABI from '@oceanprotocol/contracts/artifacts/FixedRateExchange.json' +import BigNumber from 'bignumber.js' +import { TransactionReceipt } from 'web3-core' + +export interface FixedPricedExchange { + exchangeID?: string + exchangeOwner: string + dataToken: string + baseToken: string + fixedRate: string + active: boolean + supply: string +} + +const DEFAULT_GAS_LIMIT = 200000 + +export class OceanFixedRateExchange { + /** Ocean related functions */ + public oceanAddress: string = null + public fixedRateExchangeAddress: string + public fixedRateExchangeABI: any + public web3: any + public contract: any = null + + /** + * Instantiate FixedRateExchange + * @param {any} web3 + * @param {String} fixedRateExchangeAddress + * @param {any} fixedRateExchangeABI + * @param {String} oceanAddress + */ + constructor( + web3: any, + fixedRateExchangeAddress: string = null, + fixedRateExchangeABI: any = null, + oceanAddress: string = null + ) { + this.web3 = web3 + this.fixedRateExchangeAddress = fixedRateExchangeAddress + this.fixedRateExchangeABI = fixedRateExchangeABI || defaultFixedRateExchangeABI.abi + this.oceanAddress = oceanAddress + if (web3) + this.contract = new this.web3.eth.Contract( + this.fixedRateExchangeABI, + this.fixedRateExchangeAddress + ) + } + + /** + * Creates new exchange pair between Ocean Token and data token. + * @param {String} dataToken Data Token Contract Address + * @param {Number} rate exchange rate + * @param {String} address User address + * @return {Promise} exchangeId + */ + public async create(dataToken: string, rate: string, address: string): Promise { + const estGas = await this.contract.methods + .create(this.oceanAddress, dataToken, this.web3.utils.toWei(rate)) + .estimateGas(function (err, estGas) { + if (err) console.log('FixedPriceExchange: ' + err) + return estGas + }) + const trxReceipt = await this.contract.methods + .create(this.oceanAddress, dataToken, this.web3.utils.toWei(rate)) + .send({ + from: address, + gas: estGas + 1 + }) + + let exchangeId = null + try { + exchangeId = trxReceipt.events.ExchangeCreated.returnValues[0] + } catch (e) { + console.error(e) + } + return exchangeId + } + + /** + * Creates unique exchange identifier. + * @param {String} dataToken Data Token Contract Address + * @param {String} owner Owner of the exchange + * @return {Promise} exchangeId + */ + public async generateExchangeId(dataToken: string, owner: string): Promise { + const exchangeId = await this.contract.methods + .generateExchangeId(this.oceanAddress, dataToken, owner) + .call() + return exchangeId + } + + /** + * Atomic swap + * @param {String} exchangeId ExchangeId + * @param {Number} dataTokenAmount Amount of Data Tokens + * @param {String} address User address + * @return {Promise} transaction receipt + */ + public async buyDT( + exchangeId: string, + dataTokenAmount: string, + address: string + ): Promise { + let estGas + try { + estGas = await this.contract.methods + .swap(exchangeId, this.web3.utils.toWei(String(dataTokenAmount))) + .estimateGas(function (err, g) { + if (err) { + return DEFAULT_GAS_LIMIT + } else { + return g + } + }) + } catch (e) { + estGas = DEFAULT_GAS_LIMIT + } + try { + const trxReceipt = await this.contract.methods + .swap(exchangeId, this.web3.utils.toWei(String(dataTokenAmount))) + .send({ + from: address, + gas: estGas + 1 + }) + return trxReceipt + } catch (e) { + console.error(e) + return null + } + } + + /** + * Gets total number of exchanges + * @param {String} exchangeId ExchangeId + * @param {Number} dataTokenAmount Amount of Data Tokens + * @return {Promise} no of available exchanges + */ + public async getNumberOfExchanges(): Promise { + const numExchanges = await this.contract.methods.getNumberOfExchanges().call() + return numExchanges + } + + /** + * Set new rate + * @param {String} exchangeId ExchangeId + * @param {Number} newRate New rate + * @param {String} address User account + * @return {Promise} transaction receipt + */ + public async setRate( + exchangeId: string, + newRate: number, + address: string + ): Promise { + let estGas + try { + estGas = await this.contract.methods + .setRate(exchangeId, this.web3.utils.toWei(String(newRate))) + .estimateGas(function (err, estGas) { + if (err) { + // console.log('FixedPriceExchange: ' + err) + return DEFAULT_GAS_LIMIT + } + return estGas + }) + } catch (e) { + estGas = DEFAULT_GAS_LIMIT + } + const trxReceipt = await this.contract.methods + .setRate(exchangeId, this.web3.utils.toWei(String(newRate))) + .send({ + from: address, + gas: estGas + 1 + }) + return trxReceipt + } + + /** + * Activate an exchange + * @param {String} exchangeId ExchangeId + * @param {String} address User address + * @return {Promise} transaction receipt + */ + public async activate( + exchangeId: string, + address: string + ): Promise { + let estGas + try { + estGas = await this.contract.methods + .activate(exchangeId) + .estimateGas(function (err, estGas) { + if (err) { + // console.log('FixedPriceExchange: ' + err) + estGas = DEFAULT_GAS_LIMIT + } + return estGas + }) + } catch (e) { + estGas = DEFAULT_GAS_LIMIT + } + const trxReceipt = await this.contract.methods.activate(exchangeId).send({ + from: address, + gas: estGas + 1 + }) + return trxReceipt + } + + /** + * Deactivate an exchange + * @param {String} exchangeId ExchangeId + * @param {String} address User address + * @return {Promise} transaction receipt + */ + public async deactivate( + exchangeId: string, + address: string + ): Promise { + let estGas + try { + estGas = await this.contract.methods + .deactivate(exchangeId) + .estimateGas(function (err, estGas) { + if (err) { + // console.log('FixedPriceExchange: ' + err) + estGas = DEFAULT_GAS_LIMIT + } + return estGas + }) + } catch (e) { + estGas = DEFAULT_GAS_LIMIT + } + const trxReceipt = await this.contract.methods.deactivate(exchangeId).send({ + from: address, + gas: estGas + 1 + }) + return trxReceipt + } + + /** + * Get Rate + * @param {String} exchangeId ExchangeId + * @return {Promise} Rate (converted from wei) + */ + public async getRate(exchangeId: string): Promise { + const weiRate = await this.contract.methods.getRate(exchangeId).call() + return this.web3.utils.fromWei(weiRate) + } + + /** + * Get Supply + * @param {String} exchangeId ExchangeId + * @return {Promise} Rate (converted from wei) + */ + public async getSupply(exchangeId: string): Promise { + const weiRate = await this.contract.methods.getSupply(exchangeId).call() + return this.web3.utils.fromWei(weiRate) + } + + /** + * getOceanNeeded + * @param {String} exchangeId ExchangeId + * @param {Number} dataTokenAmount Amount of Data Tokens + * @return {Promise} Ocean amount needed + */ + public async getOceanNeeded( + exchangeId: string, + dataTokenAmount: string + ): Promise { + const weiRate = await this.contract.methods + .CalcInGivenOut(exchangeId, this.web3.utils.toWei(dataTokenAmount)) + .call() + return this.web3.utils.fromWei(weiRate) + } + + /** + * Get exchange details + * @param {String} exchangeId ExchangeId + * @return {Promise} Exchange details + */ + public async getExchange(exchangeId: string): Promise { + const result: FixedPricedExchange = await this.contract.methods + .getExchange(exchangeId) + .call() + return result + } + + /** + * Get all exchanges + * @param {String} exchangeId ExchangeId + * @return {Promise} Exchanges list + */ + public async getExchanges(): Promise { + return await this.contract.methods.getExchanges().call() + } + + /** + * Check if an exchange is active + * @param {String} exchangeId ExchangeId + * @return {Promise} Result + */ + public async isActive(exchangeId: string): Promise { + const result = await this.contract.methods.isActive(exchangeId).call() + return result + } + + /** + * Calculates how many basetokens are needed to get specifyed amount of datatokens + * @param {String} exchangeId ExchangeId + * @param {String} dataTokenAmount dataTokenAmount + * @return {Promise} Result + */ + public async CalcInGivenOut( + exchangeId: string, + dataTokenAmount: string + ): Promise { + const result = await this.contract.methods + .CalcInGivenOut(exchangeId, this.web3.utils.toWei(dataTokenAmount)) + .call() + return this.web3.utils.fromWei(result) + } + + public async searchforDT( + dataTokenAddress: string, + minSupply: string + ): Promise { + const result: FixedPricedExchange[] = [] + const events = await this.contract.getPastEvents('ExchangeCreated', { + filter: { datatoken: dataTokenAddress }, + fromBlock: 0, + toBlock: 'latest' + }) + for (let i = 0; i < events.length; i++) { + const constituents = await this.getExchange(events[i].returnValues[0]) + constituents.exchangeID = events[i].returnValues[0] + if (constituents.active === true) { + const supply = new BigNumber(this.web3.utils.fromWei(constituents.supply)) + const required = new BigNumber(minSupply) + if (supply >= required) { + result.push(constituents) + } + } + } + return result + } +} diff --git a/src/models/Config.ts b/src/models/Config.ts index bc6bdfdf..53dc0297 100644 --- a/src/models/Config.ts +++ b/src/models/Config.ts @@ -74,6 +74,17 @@ export class Config { */ public poolABI?: any + /** + * FixedRateExchangeAddress + * @type {string} + */ + public fixedRateExchangeAddress?: string + + /** + * FixedRateExchangeAddressABI + * @type {any} + */ + public fixedRateExchangeAddressABI?: any /** * Log level. * @type {boolean | LogLevel} diff --git a/src/ocean/Assets.ts b/src/ocean/Assets.ts index dd55d687..491dd5b1 100644 --- a/src/ocean/Assets.ts +++ b/src/ocean/Assets.ts @@ -56,7 +56,10 @@ export class Assets extends Instantiable { metadata: Metadata, publisher: Account, services: Service[] = [], - dtAddress?: string + dtAddress?: string, + name?: string, + symbol?: string, + cap?: string ): SubscribablePromise { this.logger.log('Creating asset') return new SubscribablePromise(async (observer) => { @@ -65,11 +68,20 @@ export class Assets extends Instantiable { } if (!dtAddress) { this.logger.log('Creating datatoken') + if (!name) name = 'DataToken' + if (!symbol) symbol = 'DT' + if (!cap) cap = '1410000000000000000000000000' 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()) + dtAddress = await datatokens.create( + JSON.stringify(jsonBlob), + name, + symbol, + cap, + publisher.getId() + ) this.logger.log('DataToken creted') observer.next(CreateProgressStep.DataTokenCreated) } diff --git a/src/ocean/Ocean.ts b/src/ocean/Ocean.ts index 78e0aa8b..98e8e5c4 100644 --- a/src/ocean/Ocean.ts +++ b/src/ocean/Ocean.ts @@ -13,6 +13,10 @@ import { } from '../Instantiable.abstract' import { Compute } from './Compute' import { OceanPool } from '../balancer/OceanPool' +import { + OceanFixedRateExchange, + FixedPricedExchange +} from '../exchange/FixedRateExchange' /** * Main interface for Ocean Protocol. @@ -57,6 +61,12 @@ export class Ocean extends Instantiable { instanceConfig.config.poolFactoryAddress, instanceConfig.config.oceanTokenAddress ) + instance.fixedRateExchange = new OceanFixedRateExchange( + instanceConfig.config.web3Provider, + instanceConfig.config.fixedRateExchangeAddress, + instanceConfig.config.fixedRateExchangeAddressABI, + instanceConfig.config.oceanTokenAddress + ) instance.versions = await Versions.getInstance(instanceConfig) instance.network = new Network() return instance @@ -123,6 +133,12 @@ export class Ocean extends Instantiable { */ public pool: OceanPool + /** + * Ocean FixedRateExchange submodule + * @type {OceanFixedRateExchange} + */ + public fixedRateExchange: OceanFixedRateExchange + /** * Ocean tokens submodule * @type {OceanTokens} diff --git a/src/utils/ConfigHelper.ts b/src/utils/ConfigHelper.ts index c7fb6e06..bcd98722 100644 --- a/src/utils/ConfigHelper.ts +++ b/src/utils/ConfigHelper.ts @@ -19,17 +19,19 @@ const configs = [ factoryAddress: null, metadataStoreUri: 'http://127.0.0.1:5000', providerUri: 'http://127.0.0.1:8030', - poolFactoryAddress: null + poolFactoryAddress: null, + fixedRateExchangeAddress: null }, { chainId: 4, network: 'rinkeby', url: 'https://rinkeby.infura.io/v3', - factoryAddress: '0xcDfEe5D80041224cDCe9AE2334E85B3236385EA3', + factoryAddress: '0x3ECd1429101f93149D799Ef257C07a2B1Dc30897', oceanTokenAddress: '0x8967BCF84170c91B0d24D4302C2376283b0B3a07', metadataStoreUri: 'https://aquarius.rinkeby.v3.dev-ocean.com', providerUri: 'https://provider.rinkeby.v3.dev-ocean.com', - poolFactoryAddress: '0xA4531C624A3D88323a1e178DABe1233AF178701B' + poolFactoryAddress: '0x9B90A1358fbeEC1C4bB1DA7D4E85C708f87556Ec', + fixedRateExchangeAddress: '0x991c08bD00761A299d3126a81a985329096896D4' }, { chainId: 1, @@ -39,7 +41,8 @@ const configs = [ oceanTokenAddress: '0x985dd3d42de1e256d09e1c10f112bccb8015ad41', metadataStoreUri: null, providerUri: null, - poolFactoryAddress: null + poolFactoryAddress: null, + fixedRateExchangeAddress: null } ] diff --git a/test/FixedPriceContractHandler.ts b/test/FixedPriceContractHandler.ts new file mode 100644 index 00000000..724454a6 --- /dev/null +++ b/test/FixedPriceContractHandler.ts @@ -0,0 +1,49 @@ +import Web3 from 'web3' +import { Contract } from 'web3-eth-contract' +import { AbiItem } from 'web3-utils/types' + +export class FixedPricedContractHandler { + public contract: Contract + public accounts: string[] + public contractBytecode: string + public contractAddress: string + public web3: Web3 + + constructor(contractABI: AbiItem | AbiItem[], contractBytecode: string, web3: Web3) { + this.web3 = web3 + this.contract = new this.web3.eth.Contract(contractABI) + this.contractBytecode = contractBytecode + } + + public async getAccounts() { + this.accounts = await this.web3.eth.getAccounts() + } + + public async deployContracts() { + await this.getAccounts() + // get est gascost + const estGas = await this.contract + .deploy({ + data: this.contractBytecode, + arguments: [] + }) + .estimateGas(function (err, estGas) { + if (err) console.log('DeployContracts: ' + err) + return estGas + }) + // deploy the contract and get it's address + this.contractAddress = await this.contract + .deploy({ + data: this.contractBytecode, + arguments: [] + }) + .send({ + from: this.accounts[0], + gas: estGas + 1, + gasPrice: '3000000000' + }) + .then(function (contract) { + return contract.options.address + }) + } +} diff --git a/test/TestContractHandler.ts b/test/TestContractHandler.ts index 6a4cf090..59daa253 100644 --- a/test/TestContractHandler.ts +++ b/test/TestContractHandler.ts @@ -1,7 +1,7 @@ import Web3 from 'web3' import { Contract } from 'web3-eth-contract' import { AbiItem } from 'web3-utils/types' - +const communityCollector = '0xeE9300b7961e0a01d9f0adb863C7A227A07AaD75' export class TestContractHandler { public factory: Contract public template: Contract @@ -40,7 +40,14 @@ export class TestContractHandler { estGas = await this.template .deploy({ data: this.templateBytecode, - arguments: ['Template Contract', 'TEMPLATE', minter, cap, blob] + arguments: [ + 'Template Contract', + 'TEMPLATE', + minter, + cap, + blob, + communityCollector + ] }) .estimateGas(function (err, estGas) { if (err) console.log('DeployContracts: ' + err) @@ -50,7 +57,14 @@ export class TestContractHandler { this.templateAddress = await this.template .deploy({ data: this.templateBytecode, - arguments: ['Template Contract', 'TEMPLATE', minter, cap, blob] + arguments: [ + 'Template Contract', + 'TEMPLATE', + minter, + cap, + blob, + communityCollector + ] }) .send({ from: minter, @@ -64,7 +78,7 @@ export class TestContractHandler { estGas = await this.factory .deploy({ data: this.factoryBytecode, - arguments: [this.templateAddress] + arguments: [this.templateAddress, communityCollector] }) .estimateGas(function (err, estGas) { if (err) console.log('DeployContracts: ' + err) @@ -74,7 +88,7 @@ export class TestContractHandler { this.factoryAddress = await this.factory .deploy({ data: this.factoryBytecode, - arguments: [this.templateAddress] + arguments: [this.templateAddress, communityCollector] }) .send({ from: minter, diff --git a/test/integration/ComputeFlow.test.ts b/test/integration/ComputeFlow.test.ts index 8330a4fc..3ae5e799 100644 --- a/test/integration/ComputeFlow.test.ts +++ b/test/integration/ComputeFlow.test.ts @@ -79,7 +79,13 @@ describe('Compute flow', () => { datatokensTemplate.abi as AbiItem[], web3 ) - tokenAddress = await datatoken.create(blob, alice.getId()) + tokenAddress = await datatoken.create( + blob, + 'AliceDT', + 'DTA', + '10000000000', + alice.getId() + ) assert(tokenAddress != null) }) diff --git a/test/integration/Marketplaceflow.test.ts b/test/integration/Marketplaceflow.test.ts index a70aa8a6..480f6ece 100644 --- a/test/integration/Marketplaceflow.test.ts +++ b/test/integration/Marketplaceflow.test.ts @@ -57,7 +57,13 @@ describe('Marketplace flow', () => { datatokensTemplate.abi as AbiItem[], web3 ) - tokenAddress = await datatoken.create(blob, alice.getId()) + tokenAddress = await datatoken.create( + blob, + 'AliceDT', + 'DTA', + '10000000000', + alice.getId() + ) assert(tokenAddress != null) }) diff --git a/test/integration/Simpleflow.test.ts b/test/integration/Simpleflow.test.ts index 27086427..bddfacc5 100644 --- a/test/integration/Simpleflow.test.ts +++ b/test/integration/Simpleflow.test.ts @@ -41,7 +41,7 @@ describe('Simple flow', () => { datatokensTemplate.abi as AbiItem[], web3 ) - tokenAddress = await datatoken.create(blob, alice) + tokenAddress = await datatoken.create(blob, 'AliceDT', 'DTA', '10000000000', alice) }) it('Alice mints 100 tokens', async () => { await datatoken.mint(tokenAddress, alice, tokenAmount) diff --git a/test/unit/Datatokens.test.ts b/test/unit/Datatokens.test.ts index bdd39fb3..2e1a9dfe 100644 --- a/test/unit/Datatokens.test.ts +++ b/test/unit/Datatokens.test.ts @@ -45,7 +45,7 @@ describe('DataTokens', () => { }) it('should create datatokens smart contract', async () => { - tokenAddress = await datatoken.create(blob, minter) + tokenAddress = await datatoken.create(blob, 'AliceDT', 'DTA', '10000000000', minter) assert(tokenAddress !== null) }) diff --git a/test/unit/balancer/Balancer.test.ts b/test/unit/balancer/Balancer.test.ts index d1cdefa2..4d4a6ab5 100644 --- a/test/unit/balancer/Balancer.test.ts +++ b/test/unit/balancer/Balancer.test.ts @@ -10,8 +10,8 @@ import factory from '@oceanprotocol/contracts/artifacts/DTFactory.json' import datatokensTemplate from '@oceanprotocol/contracts/artifacts/DataTokenTemplate.json' // this will be replaced by our SFactory/SPool -import OceanPoolFactory from '@oceanprotocol/contracts/artifacts/SFactory.json' -import OceanSPool from '@oceanprotocol/contracts/artifacts/SPool.json' +import OceanPoolFactory from '@oceanprotocol/contracts/artifacts/BFactory.json' +import OceanSPool from '@oceanprotocol/contracts/artifacts/BPool.json' const web3 = new Web3('http://127.0.0.1:8545') describe('Balancer flow', () => { @@ -74,7 +74,7 @@ describe('Balancer flow', () => { }) it('should create datatokens smart contract', async () => { - tokenAddress = await datatoken.create(blob, alice) + tokenAddress = await datatoken.create(blob, 'AliceDT', 'DTA', '10000000000', alice) assert(tokenAddress !== null) }) it('Create a dummy OceanToken', async () => { @@ -85,7 +85,13 @@ describe('Balancer flow', () => { datatokensTemplate.abi as AbiItem[], web3 ) - oceanTokenAddress = await oceandatatoken.create(blob, alice) + oceanTokenAddress = await oceandatatoken.create( + blob, + 'AliceDT2', + 'DTA2', + '10000000000', + alice + ) }) it('should initialize OceanPool class', async () => { Pool = new OceanPool( diff --git a/test/unit/exchanges/FixedPriceExchange.test.ts b/test/unit/exchanges/FixedPriceExchange.test.ts new file mode 100644 index 00000000..95011b03 --- /dev/null +++ b/test/unit/exchanges/FixedPriceExchange.test.ts @@ -0,0 +1,233 @@ +import { assert } from 'chai' +import { AbiItem } from 'web3-utils/types' +import { TestContractHandler } from '../../TestContractHandler' +import { FixedPricedContractHandler } from '../../FixedPriceContractHandler' +import { DataTokens } from '../../../src/datatokens/Datatokens' +import { + OceanFixedRateExchange, + FixedPricedExchange +} from '../../../src/exchange/FixedRateExchange' + +import Web3 from 'web3' +import factory from '@oceanprotocol/contracts/artifacts/DTFactory.json' +import datatokensTemplate from '@oceanprotocol/contracts/artifacts/DataTokenTemplate.json' + +import BigNumber from 'bignumber.js' +import FixedRateExchangeContract = require('@oceanprotocol/contracts/artifacts/FixedRateExchange.json') +const web3 = new Web3('http://127.0.0.1:8545') + +describe('FixedRateExchange flow', () => { + let oceanTokenAddress + let FixedRateExchangeAddress + let FixedRateClass + let oceandatatoken + let aliceExchangeId + let bob + let alice + let datatoken + let tokenAddress + + let alicePoolAddress + let currentDtPrice + let owner + let contracts + + const consoleDebug = false + let greatPool + const tokenAmount = '1000000000000000000000000000000000' + const fixedPriceRate = '0.5' + const updatedPriceRate = '2' + const swapAmount = '1' + const blob = 'http://localhost:8030/api/v1/services/consume' + describe('#test', () => { + before(async () => { + // deploy SFactory + const Contracts = new FixedPricedContractHandler( + FixedRateExchangeContract.abi as AbiItem[], + FixedRateExchangeContract.bytecode, + web3 + ) + await Contracts.getAccounts() + owner = Contracts.accounts[0] + + await Contracts.deployContracts() + FixedRateExchangeAddress = Contracts.contractAddress + assert(FixedRateExchangeAddress !== null) + + // deploy DT Factory + contracts = new TestContractHandler( + factory.abi as AbiItem[], + datatokensTemplate.abi as AbiItem[], + 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 as AbiItem[], + datatokensTemplate.abi as AbiItem[], + web3 + ) + assert(datatoken !== null) + }) + + it('should create datatokens smart contract', async () => { + tokenAddress = await datatoken.create( + blob, + 'AliceDT', + 'DTA', + web3.utils.toWei('1000000000000000'), + alice + ) + assert(tokenAddress !== null) + if (consoleDebug) console.log("Alice's address:" + alice) + if (consoleDebug) console.log('data Token address:' + tokenAddress) + }) + it('Create a dummy OceanToken', async () => { + // Bob creates a Datatoken + oceandatatoken = new DataTokens( + contracts.factoryAddress, + factory.abi as AbiItem[], + datatokensTemplate.abi as AbiItem[], + web3 + ) + oceanTokenAddress = await oceandatatoken.create( + blob, + 'BobDT', + 'DTB', + web3.utils.toWei('1000000000000000'), + bob + ) + if (consoleDebug) console.log("Bob's address:" + bob) + if (consoleDebug) console.log('oceanTokenAddress:' + oceanTokenAddress) + }) + + it('should initialize FixedExchangeRate class', async () => { + FixedRateClass = new OceanFixedRateExchange( + web3, + FixedRateExchangeAddress, + FixedRateExchangeContract.abi, + oceanTokenAddress + ) + assert(FixedRateClass !== null) + }) + + it('Alice mints 1000 tokens', async () => { + const txid = await datatoken.mint(tokenAddress, alice, tokenAmount) + if (consoleDebug) console.log(txid) + assert(txid !== null) + }) + it('Bob mints 1000 Ocean tokens', async () => { + const txid = await oceandatatoken.mint(oceanTokenAddress, bob, tokenAmount) + if (consoleDebug) console.log(txid) + assert(txid !== null) + }) + it('Alice should have 1000 tokens', async () => { + const balance = await datatoken.balance(tokenAddress, alice) + if (consoleDebug) console.log("Alice's datatoke balance:" + balance) + }) + it('Bob should have 1000 ocean tokens', async () => { + const balance = await oceandatatoken.balance(oceanTokenAddress, bob) + if (consoleDebug) console.log("Bob's ocean balance:" + balance) + }) + it('Alice allows Exchange to spend 1000 data tokens', async () => { + const txid = await datatoken.approve( + tokenAddress, + FixedRateExchangeAddress, + tokenAmount, + alice + ) + if (consoleDebug) console.log(txid) + }) + it('Bob allows Exchange to spend 1000 ocean tokens', async () => { + const txid = await oceandatatoken.approve( + oceanTokenAddress, + FixedRateExchangeAddress, + tokenAmount, + bob + ) + if (consoleDebug) console.log(txid) + }) + it('Alice should aproved speding datatokens', async () => { + const balance = await datatoken.allowance( + tokenAddress, + alice, + FixedRateExchangeAddress + ) + if (consoleDebug) console.log('Alice datatoken allowance:' + balance) + }) + it('Bob should aproved speding oceantokens', async () => { + const balance = await oceandatatoken.allowance( + oceanTokenAddress, + bob, + FixedRateExchangeAddress + ) + if (consoleDebug) console.log('Bob ocean allowance:' + balance) + }) + it('Alice creates a new FixedRate Exchange with a rate of 0.5', async () => { + aliceExchangeId = await FixedRateClass.create(tokenAddress, fixedPriceRate, alice) + if (consoleDebug) console.log('aliceExchangeId:' + aliceExchangeId) + }) + it('Bob should find the exchange', async () => { + const exchangeDetails = await FixedRateClass.searchforDT(tokenAddress, '0') + assert(exchangeDetails[0].exchangeID === aliceExchangeId) + }) + it('Bob should get the exchange details', async () => { + const exchangeDetails = await FixedRateClass.getExchange(aliceExchangeId) + if (consoleDebug) console.log(exchangeDetails) + }) + + it('Bob should get the amount of Ocean needed', async () => { + const OceansNeeded = await FixedRateClass.CalcInGivenOut( + aliceExchangeId, + swapAmount + ) + if (consoleDebug) console.log('Oceans needed:' + OceansNeeded) + assert(OceansNeeded !== null) + }) + it('Bob should swap 1 DataToken', async () => { + const swapResult = await FixedRateClass.buyDT(aliceExchangeId, swapAmount, bob) + if (consoleDebug) console.log(swapResult) + assert(swapResult !== null) + }) + it('Alice datatoken balance after swap', async () => { + const balance = await datatoken.balance(tokenAddress, alice) + if (consoleDebug) console.log('Alice datatoken balance:' + balance) + }) + it('Alice ocean balance after swap', async () => { + const balance = await oceandatatoken.balance(oceanTokenAddress, alice) + if (consoleDebug) console.log('Alice ocean balance:' + balance) + }) + it('Bob datatoken balance after swap', async () => { + const balance = await datatoken.balance(tokenAddress, bob) + if (consoleDebug) console.log('Bob datatoken balance:' + balance) + }) + it('Bob ocean balance after swap', async () => { + const balance = await oceandatatoken.balance(oceanTokenAddress, bob) + if (consoleDebug) console.log('Bob ocean balance:' + balance) + }) + it('Alice should update the rate', async () => { + const tx = await FixedRateClass.setRate(aliceExchangeId, updatedPriceRate, alice) + assert(tx !== null) + }) + it('Alice should be able to deactivate the exchange', async () => { + const tx = await FixedRateClass.deactivate(aliceExchangeId, alice) + assert(tx !== null) + const exchangeDetails = await FixedRateClass.getExchange(aliceExchangeId) + assert(exchangeDetails.active === false) + }) + it('Alice should be able to activate the exchange', async () => { + const tx = await FixedRateClass.activate(aliceExchangeId, alice) + assert(tx !== null) + const exchangeDetails = await FixedRateClass.getExchange(aliceExchangeId) + assert(exchangeDetails.active === true) + }) + }) +})