diff --git a/CodeExamples.md b/CodeExamples.md index c9558cbd..3e276a51 100644 --- a/CodeExamples.md +++ b/CodeExamples.md @@ -1,5 +1,5 @@ # Ocean.js Code Examples - + ## Introduction The following guide runs you through the process of using ocean.js to publish and then consume a dataset. The code examples below are all working and you can learn how to publish by following along. diff --git a/package-lock.json b/package-lock.json index 21e270d5..d9e33f97 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,7 +24,7 @@ "@types/chai-spies": "^1.0.3", "@types/crypto-js": "^4.1.1", "@types/mocha": "^9.1.1", - "@types/node": "^17.0.34", + "@types/node": "^17.0.35", "@types/node-fetch": "^3.0.3", "@typescript-eslint/eslint-plugin": "^4.33.0", "@typescript-eslint/parser": "^4.33.0", @@ -45,7 +45,7 @@ "prettier": "^2.6.2", "release-it": "^15.0.0", "source-map-support": "^0.5.19", - "ts-node": "^10.7.0", + "ts-node": "^10.8.0", "ts-node-register": "^1.0.0", "typedoc": "0.22.15", "typescript": "^4.6.4" @@ -1911,22 +1911,13 @@ "node": ">=6.9.0" } }, - "node_modules/@cspotcode/source-map-consumer": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz", - "integrity": "sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==", - "dev": true, - "engines": { - "node": ">= 12" - } - }, "node_modules/@cspotcode/source-map-support": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz", - "integrity": "sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA==", + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", "dev": true, "dependencies": { - "@cspotcode/source-map-consumer": "0.8.0" + "@jridgewell/trace-mapping": "0.3.9" }, "engines": { "node": ">=12" @@ -2411,6 +2402,31 @@ "node": ">=8" } }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.7.tgz", + "integrity": "sha512-8cXDaBBHOr2pQ7j77Y6Vp5VDT2sIqWyWQ56TjEq4ih/a4iST3dItRe8Q9fp0rrIl9DoKhWQtUQz/YpOxLkXbNA==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.13", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.13.tgz", + "integrity": "sha512-GryiOJmNcWbovBxTfZSF71V/mXbgcV3MewDe3kIMCLyIh5e7SKAeUZs+rMnJ8jkMolZ/4/VsdBmMrw3l+VdZ3w==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, "node_modules/@metamask/safe-event-emitter": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@metamask/safe-event-emitter/-/safe-event-emitter-2.0.0.tgz", @@ -3021,9 +3037,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "17.0.34", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.34.tgz", - "integrity": "sha512-XImEz7XwTvDBtzlTnm8YvMqGW/ErMWBsKZ+hMTvnDIjGCKxwK5Xpc+c/oQjOauwq8M4OS11hEkpjX8rrI/eEgA==" + "version": "17.0.35", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.35.tgz", + "integrity": "sha512-vu1SrqBjbbZ3J6vwY17jBs8Sr/BKA+/a/WtjRG+whKg1iuLFOosq872EXS0eXWILdO36DHQQeku/ZcL6hz2fpg==" }, "node_modules/@types/node-fetch": { "version": "3.0.3", @@ -16285,12 +16301,12 @@ "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" }, "node_modules/ts-node": { - "version": "10.7.0", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.7.0.tgz", - "integrity": "sha512-TbIGS4xgJoX2i3do417KSaep1uRAW/Lu+WAL2doDHC0D6ummjirVOXU5/7aiZotbQ5p1Zp9tP7U6cYhA0O7M8A==", + "version": "10.8.0", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.8.0.tgz", + "integrity": "sha512-/fNd5Qh+zTt8Vt1KbYZjRHCE9sI5i7nqfD/dzBBRDeVXZXS6kToW6R7tTU6Nd4XavFs0mAVCg29Q//ML7WsZYA==", "dev": true, "dependencies": { - "@cspotcode/source-map-support": "0.7.0", + "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", "@tsconfig/node12": "^1.0.7", "@tsconfig/node14": "^1.0.0", @@ -16301,7 +16317,7 @@ "create-require": "^1.1.0", "diff": "^4.0.1", "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.0", + "v8-compile-cache-lib": "^3.0.1", "yn": "3.1.1" }, "bin": { @@ -16885,9 +16901,9 @@ "dev": true }, "node_modules/v8-compile-cache-lib": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.0.tgz", - "integrity": "sha512-mpSYqfsFvASnSn5qMiwrr4VKfumbPyONLCOPmsR3A6pTY/r0+tSaVbgPWSAIuzbk3lCTa+FForeTiO+wBQGkjA==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", "dev": true }, "node_modules/varint": { @@ -19258,19 +19274,13 @@ "to-fast-properties": "^2.0.0" } }, - "@cspotcode/source-map-consumer": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz", - "integrity": "sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==", - "dev": true - }, "@cspotcode/source-map-support": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz", - "integrity": "sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA==", + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", "dev": true, "requires": { - "@cspotcode/source-map-consumer": "0.8.0" + "@jridgewell/trace-mapping": "0.3.9" } }, "@eslint/eslintrc": { @@ -19565,6 +19575,28 @@ "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", "dev": true }, + "@jridgewell/resolve-uri": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.7.tgz", + "integrity": "sha512-8cXDaBBHOr2pQ7j77Y6Vp5VDT2sIqWyWQ56TjEq4ih/a4iST3dItRe8Q9fp0rrIl9DoKhWQtUQz/YpOxLkXbNA==", + "dev": true + }, + "@jridgewell/sourcemap-codec": { + "version": "1.4.13", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.13.tgz", + "integrity": "sha512-GryiOJmNcWbovBxTfZSF71V/mXbgcV3MewDe3kIMCLyIh5e7SKAeUZs+rMnJ8jkMolZ/4/VsdBmMrw3l+VdZ3w==", + "dev": true + }, + "@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, "@metamask/safe-event-emitter": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@metamask/safe-event-emitter/-/safe-event-emitter-2.0.0.tgz", @@ -20079,9 +20111,9 @@ "dev": true }, "@types/node": { - "version": "17.0.34", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.34.tgz", - "integrity": "sha512-XImEz7XwTvDBtzlTnm8YvMqGW/ErMWBsKZ+hMTvnDIjGCKxwK5Xpc+c/oQjOauwq8M4OS11hEkpjX8rrI/eEgA==" + "version": "17.0.35", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.35.tgz", + "integrity": "sha512-vu1SrqBjbbZ3J6vwY17jBs8Sr/BKA+/a/WtjRG+whKg1iuLFOosq872EXS0eXWILdO36DHQQeku/ZcL6hz2fpg==" }, "@types/node-fetch": { "version": "3.0.3", @@ -30239,12 +30271,12 @@ "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" }, "ts-node": { - "version": "10.7.0", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.7.0.tgz", - "integrity": "sha512-TbIGS4xgJoX2i3do417KSaep1uRAW/Lu+WAL2doDHC0D6ummjirVOXU5/7aiZotbQ5p1Zp9tP7U6cYhA0O7M8A==", + "version": "10.8.0", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.8.0.tgz", + "integrity": "sha512-/fNd5Qh+zTt8Vt1KbYZjRHCE9sI5i7nqfD/dzBBRDeVXZXS6kToW6R7tTU6Nd4XavFs0mAVCg29Q//ML7WsZYA==", "dev": true, "requires": { - "@cspotcode/source-map-support": "0.7.0", + "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", "@tsconfig/node12": "^1.0.7", "@tsconfig/node14": "^1.0.0", @@ -30255,7 +30287,7 @@ "create-require": "^1.1.0", "diff": "^4.0.1", "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.0", + "v8-compile-cache-lib": "^3.0.1", "yn": "3.1.1" }, "dependencies": { @@ -30684,9 +30716,9 @@ "dev": true }, "v8-compile-cache-lib": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.0.tgz", - "integrity": "sha512-mpSYqfsFvASnSn5qMiwrr4VKfumbPyONLCOPmsR3A6pTY/r0+tSaVbgPWSAIuzbk3lCTa+FForeTiO+wBQGkjA==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", "dev": true }, "varint": { @@ -31570,4 +31602,4 @@ "dev": true } } -} +} \ No newline at end of file diff --git a/package.json b/package.json index 3bb3cca3..5df019a8 100644 --- a/package.json +++ b/package.json @@ -77,7 +77,7 @@ "@types/chai-spies": "^1.0.3", "@types/crypto-js": "^4.1.1", "@types/mocha": "^9.1.1", - "@types/node": "^17.0.34", + "@types/node": "^17.0.35", "@types/node-fetch": "^3.0.3", "@typescript-eslint/eslint-plugin": "^4.33.0", "@typescript-eslint/parser": "^4.33.0", @@ -98,7 +98,7 @@ "prettier": "^2.6.2", "release-it": "^15.0.0", "source-map-support": "^0.5.19", - "ts-node": "^10.7.0", + "ts-node": "^10.8.0", "ts-node-register": "^1.0.0", "typedoc": "0.22.15", "typescript": "^4.6.4" diff --git a/src/@types/Erc20.ts b/src/@types/Erc20.ts index 9c133ff7..19643b47 100644 --- a/src/@types/Erc20.ts +++ b/src/@types/Erc20.ts @@ -15,3 +15,9 @@ export interface ConsumeMarketFee { consumeMarketFeeToken: string // address of the token marketplace wants to add fee on top consumeMarketFeeAmount: string } + +export interface PublishingMarketFee { + publishMarketFeeAddress: string + publishMarketFeeToken: string + publishMarketFeeAmount: string +} diff --git a/src/pools/fixedRate/FixedRateExchange.ts b/src/pools/fixedRate/FixedRateExchange.ts index 75c381cf..ca3e5bd9 100644 --- a/src/pools/fixedRate/FixedRateExchange.ts +++ b/src/pools/fixedRate/FixedRateExchange.ts @@ -60,9 +60,8 @@ export class FixedRateExchange { public oceanAddress: string = null public fixedRateAddress: string public fixedRateExchangeAbi: AbiItem | AbiItem[] - public fixedRateContract: Contract public web3: Web3 - public contract: Contract = null + public fixedRateContract: Contract = null public config: Config public ssAbi: AbiItem | AbiItem[] @@ -86,7 +85,7 @@ export class FixedRateExchange { fixedRateExchangeAbi || (defaultFixedRateExchangeAbi.abi as AbiItem[]) this.oceanAddress = oceanAddress this.fixedRateAddress = fixedRateAddress - this.contract = setContractDefaults( + this.fixedRateContract = setContractDefaults( new this.web3.eth.Contract(this.fixedRateExchangeAbi, this.fixedRateAddress), this.config ) @@ -115,7 +114,7 @@ export class FixedRateExchange { * @return {Promise} exchangeId */ public async generateExchangeId(baseToken: string, datatoken: string): Promise { - const exchangeId = await this.contract.methods + const exchangeId = await this.fixedRateContract.methods .generateExchangeId(baseToken, datatoken) .call() return exchangeId @@ -186,7 +185,7 @@ export class FixedRateExchange { const estGas = await estimateGas( address, - this.contract.methods.buyDT, + this.fixedRateContract.methods.buyDT, exchangeId, dtAmountFormatted, maxBtFormatted, @@ -194,7 +193,7 @@ export class FixedRateExchange { consumeMarketFeeFormatted ) try { - const trxReceipt = await this.contract.methods + const trxReceipt = await this.fixedRateContract.methods .buyDT( exchangeId, dtAmountFormatted, @@ -278,7 +277,7 @@ export class FixedRateExchange { ) const estGas = await estimateGas( address, - this.contract.methods.sellDT, + this.fixedRateContract.methods.sellDT, exchangeId, dtAmountFormatted, minBtFormatted, @@ -286,7 +285,7 @@ export class FixedRateExchange { consumeMarketFeeFormatted ) try { - const trxReceipt = await this.contract.methods + const trxReceipt = await this.fixedRateContract.methods .sellDT( exchangeId, dtAmountFormatted, @@ -313,7 +312,9 @@ export class FixedRateExchange { * @return {Promise} no of available exchanges */ public async getNumberOfExchanges(): Promise { - const numExchanges = await this.contract.methods.getNumberOfExchanges().call() + const numExchanges = await this.fixedRateContract.methods + .getNumberOfExchanges() + .call() return numExchanges } @@ -355,11 +356,11 @@ export class FixedRateExchange { ): Promise { const estGas = await estimateGas( address, - this.contract.methods.setRate, + this.fixedRateContract.methods.setRate, exchangeId, this.web3.utils.toWei(newRate) ) - const trxReceipt = await this.contract.methods + const trxReceipt = await this.fixedRateContract.methods .setRate(exchangeId, this.web3.utils.toWei(newRate)) .send({ from: address, @@ -385,7 +386,12 @@ export class FixedRateExchange { ): Promise { const fixedRate = contractInstance || this.fixedRateContract - return estimateGas(account, fixedRate.methods.setRate, exchangeId, newAllowedSwapper) + return estimateGas( + account, + fixedRate.methods.setAllowedSwapper, + exchangeId, + newAllowedSwapper + ) } /** @@ -402,11 +408,11 @@ export class FixedRateExchange { ): Promise { const estGas = await estimateGas( address, - this.contract.methods.setAllowedSwapper, + this.fixedRateContract.methods.setAllowedSwapper, exchangeId, newAllowedSwapper ) - const trxReceipt = await this.contract.methods + const trxReceipt = await this.fixedRateContract.methods .setAllowedSwapper(exchangeId, newAllowedSwapper) .send({ from: address, @@ -446,17 +452,18 @@ export class FixedRateExchange { const exchange = await this.getExchange(exchangeId) if (!exchange) return null if (exchange.active === true) return null - const estGas = await estimateGas( address, - this.contract.methods.toggleExchangeState, + this.fixedRateContract.methods.toggleExchangeState, exchangeId ) - const trxReceipt = await this.contract.methods.toggleExchangeState(exchangeId).send({ - from: address, - gas: estGas + 1, - gasPrice: await getFairGasPrice(this.web3, this.config) - }) + const trxReceipt = await this.fixedRateContract.methods + .toggleExchangeState(exchangeId) + .send({ + from: address, + gas: estGas + 1, + gasPrice: await getFairGasPrice(this.web3, this.config) + }) return trxReceipt } @@ -493,15 +500,17 @@ export class FixedRateExchange { const estGas = await estimateGas( address, - this.contract.methods.toggleExchangeState, + this.fixedRateContract.methods.toggleExchangeState, exchangeId ) - const trxReceipt = await this.contract.methods.toggleExchangeState(exchangeId).send({ - from: address, - gas: estGas + 1, - gasPrice: await getFairGasPrice(this.web3, this.config) - }) + const trxReceipt = await this.fixedRateContract.methods + .toggleExchangeState(exchangeId) + .send({ + from: address, + gas: estGas + 1, + gasPrice: await getFairGasPrice(this.web3, this.config) + }) return trxReceipt } @@ -512,7 +521,7 @@ export class FixedRateExchange { * @return {Promise} Rate (converted from wei) */ public async getRate(exchangeId: string): Promise { - const weiRate = await this.contract.methods.getRate(exchangeId).call() + const weiRate = await this.fixedRateContract.methods.getRate(exchangeId).call() const rate = await this.web3.utils.fromWei(weiRate) return rate } @@ -523,7 +532,7 @@ export class FixedRateExchange { * @return {Promise} dt supply formatted */ public async getDTSupply(exchangeId: string): Promise { - const dtSupply = await this.contract.methods.getDTSupply(exchangeId).call() + const dtSupply = await this.fixedRateContract.methods.getDTSupply(exchangeId).call() const exchange = await this.getExchange(exchangeId) return await this.unitsToAmount(exchange.datatoken, dtSupply, +exchange.dtDecimals) } @@ -534,7 +543,7 @@ export class FixedRateExchange { * @return {Promise} dt supply formatted */ public async getBTSupply(exchangeId: string): Promise { - const btSupply = await this.contract.methods.getBTSupply(exchangeId).call() + const btSupply = await this.fixedRateContract.methods.getBTSupply(exchangeId).call() const exchange = await this.getExchange(exchangeId) return await this.unitsToAmount(exchange.baseToken, btSupply, +exchange.btDecimals) } @@ -545,7 +554,7 @@ export class FixedRateExchange { * @return {Promise} address of allowedSwapper */ public async getAllowedSwapper(exchangeId: string): Promise { - return await this.contract.methods.getAllowedSwapper(exchangeId).call() + return await this.fixedRateContract.methods.getAllowedSwapper(exchangeId).call() } /** @@ -561,7 +570,7 @@ export class FixedRateExchange { consumeMarketFee: string = '0' ): Promise { const fixedRateExchange = await this.getExchange(exchangeId) - const result = await this.contract.methods + const result = await this.fixedRateContract.methods .calcBaseInGivenOutDT( exchangeId, await this.amountToUnits( @@ -611,7 +620,7 @@ export class FixedRateExchange { consumeMarketFee: string = '0' ): Promise { const exchange = await this.getExchange(exchangeId) - const result = await this.contract.methods + const result = await this.fixedRateContract.methods .calcBaseOutGivenInDT( exchangeId, await this.amountToUnits( @@ -632,7 +641,7 @@ export class FixedRateExchange { * @return {Promise} Exchange details */ public async getExchange(exchangeId: string): Promise { - const result: FixedPriceExchange = await this.contract.methods + const result: FixedPriceExchange = await this.fixedRateContract.methods .getExchange(exchangeId) .call() result.dtDecimals = result.dtDecimals.toString() @@ -668,7 +677,9 @@ export class FixedRateExchange { * @return {Promise} Exchange details */ public async getFeesInfo(exchangeId: string): Promise { - const result: FeesInfo = await this.contract.methods.getFeesInfo(exchangeId).call() + const result: FeesInfo = await this.fixedRateContract.methods + .getFeesInfo(exchangeId) + .call() result.opcFee = this.web3.utils.fromWei(result.opcFee.toString()) result.marketFee = this.web3.utils.fromWei(result.marketFee.toString()) @@ -694,7 +705,7 @@ export class FixedRateExchange { * @return {Promise} Exchanges list */ public async getExchanges(): Promise { - return await this.contract.methods.getExchanges().call() + return await this.fixedRateContract.methods.getExchanges().call() } /** @@ -703,7 +714,7 @@ export class FixedRateExchange { * @return {Promise} Result */ public async isActive(exchangeId: string): Promise { - const result = await this.contract.methods.isActive(exchangeId).call() + const result = await this.fixedRateContract.methods.isActive(exchangeId).call() return result } @@ -740,11 +751,11 @@ export class FixedRateExchange { const estGas = await estimateGas( address, - this.contract.methods.toggleMintState, + this.fixedRateContract.methods.toggleMintState, exchangeId, true ) - const trxReceipt = await this.contract.methods + const trxReceipt = await this.fixedRateContract.methods .toggleMintState(exchangeId, true) .send({ from: address, @@ -768,7 +779,12 @@ export class FixedRateExchange { ): Promise { const fixedRate = contractInstance || this.fixedRateContract - return estimateGas(account, fixedRate.methods.toggleMintState, exchangeId) + return estimateGas( + account, + fixedRate.methods.toggleMintState(exchangeId, false), + exchangeId, + false + ) } /** @@ -787,12 +803,12 @@ export class FixedRateExchange { const estGas = await estimateGas( address, - this.contract.methods.toggleMintState, + this.fixedRateContract.methods.toggleMintState, exchangeId, false ) - const trxReceipt = await this.contract.methods + const trxReceipt = await this.fixedRateContract.methods .toggleMintState(exchangeId, false) .send({ from: address, @@ -818,7 +834,7 @@ export class FixedRateExchange { contractInstance?: Contract ): Promise { const fixedRate = contractInstance || this.fixedRateContract - const fixedrate: FixedPriceExchange = await this.contract.methods + const fixedrate: FixedPriceExchange = await this.fixedRateContract.methods .getExchange(exchangeId) .call() const amountWei = await this.amountToUnits( @@ -844,7 +860,7 @@ export class FixedRateExchange { const exchange = await this.getExchange(exchangeId) if (!exchange) return null - const fixedrate: FixedPriceExchange = await this.contract.methods + const fixedrate: FixedPriceExchange = await this.fixedRateContract.methods .getExchange(exchangeId) .call() const amountWei = await this.amountToUnits( @@ -855,16 +871,18 @@ export class FixedRateExchange { const estGas = await estimateGas( address, - this.contract.methods.collectBT, + this.fixedRateContract.methods.collectBT, exchangeId, amountWei ) - const trxReceipt = await this.contract.methods.collectBT(exchangeId, amountWei).send({ - from: address, - gas: estGas + 1, - gasPrice: await getFairGasPrice(this.web3, this.config) - }) + const trxReceipt = await this.fixedRateContract.methods + .collectBT(exchangeId, amountWei) + .send({ + from: address, + gas: estGas + 1, + gasPrice: await getFairGasPrice(this.web3, this.config) + }) return trxReceipt } @@ -883,7 +901,7 @@ export class FixedRateExchange { contractInstance?: Contract ): Promise { const fixedRate = contractInstance || this.fixedRateContract - const fixedrate: FixedPriceExchange = await this.contract.methods + const fixedrate: FixedPriceExchange = await this.fixedRateContract.methods .getExchange(exchangeId) .call() @@ -910,7 +928,7 @@ export class FixedRateExchange { const exchange = await this.getExchange(exchangeId) if (!exchange) return null - const fixedrate: FixedPriceExchange = await this.contract.methods + const fixedrate: FixedPriceExchange = await this.fixedRateContract.methods .getExchange(exchangeId) .call() const amountWei = await this.amountToUnits( @@ -921,16 +939,18 @@ export class FixedRateExchange { const estGas = await estimateGas( address, - this.contract.methods.collectDT, + this.fixedRateContract.methods.collectDT, exchangeId, amountWei ) - const trxReceipt = await this.contract.methods.collectDT(exchangeId, amountWei).send({ - from: address, - gas: estGas + 1, - gasPrice: await getFairGasPrice(this.web3, this.config) - }) + const trxReceipt = await this.fixedRateContract.methods + .collectDT(exchangeId, amountWei) + .send({ + from: address, + gas: estGas + 1, + gasPrice: await getFairGasPrice(this.web3, this.config) + }) return trxReceipt } @@ -966,14 +986,16 @@ export class FixedRateExchange { const estGas = await estimateGas( address, - this.contract.methods.collectMarketFee, + this.fixedRateContract.methods.collectMarketFee, exchangeId ) - const trxReceipt = await this.contract.methods.collectMarketFee(exchangeId).send({ - from: address, - gas: estGas + 1, - gasPrice: await getFairGasPrice(this.web3, this.config) - }) + const trxReceipt = await this.fixedRateContract.methods + .collectMarketFee(exchangeId) + .send({ + from: address, + gas: estGas + 1, + gasPrice: await getFairGasPrice(this.web3, this.config) + }) return trxReceipt } @@ -1009,17 +1031,33 @@ export class FixedRateExchange { const estGas = await estimateGas( address, - this.contract.methods.collectOceanFee, + this.fixedRateContract.methods.collectOceanFee, exchangeId ) - const trxReceipt = await this.contract.methods.collectOceanFee(exchangeId).send({ - from: address, - gas: estGas + 1, - gasPrice: await getFairGasPrice(this.web3, this.config) - }) + const trxReceipt = await this.fixedRateContract.methods + .collectOceanFee(exchangeId) + .send({ + from: address, + gas: estGas + 1, + gasPrice: await getFairGasPrice(this.web3, this.config) + }) return trxReceipt } + /** + * Get OPF Collector of fixed rate contract + * @return {String} + */ + async getOPCCollector(): Promise { + let result = null + try { + result = await this.fixedRateContract.methods.opcCollector().call() + } catch (e) { + LoggerInstance.error(`ERROR: Failed to get OPC Collector address: ${e.message}`) + } + return result + } + /** * Get Router address set in fixed rate contract * @return {String} @@ -1027,7 +1065,7 @@ export class FixedRateExchange { async getRouter(): Promise { let result = null try { - result = await this.contract.methods.router().call() + result = await this.fixedRateContract.methods.router().call() } catch (e) { LoggerInstance.error(`ERROR: Failed to get Router address: ${e.message}`) } @@ -1087,11 +1125,11 @@ export class FixedRateExchange { ): Promise { const estGas = await estimateGas( address, - this.contract.methods.updateMarketFee, + this.fixedRateContract.methods.updateMarketFee, exchangeId, this.web3.utils.toWei(newMarketFee) ) - const trxReceipt = await this.contract.methods + const trxReceipt = await this.fixedRateContract.methods .updateMarketFee(exchangeId, this.web3.utils.toWei(newMarketFee)) .send({ from: address, @@ -1139,11 +1177,11 @@ export class FixedRateExchange { ): Promise { const estGas = await estimateGas( address, - this.contract.methods.updateMarketFeeCollector, + this.fixedRateContract.methods.updateMarketFeeCollector, exchangeId, newMarketFeeCollector ) - const trxReceipt = await this.contract.methods + const trxReceipt = await this.fixedRateContract.methods .updateMarketFeeCollector(exchangeId, newMarketFeeCollector) .send({ from: address, diff --git a/src/tokens/Datatoken.ts b/src/tokens/Datatoken.ts index 152cc498..5c155d5d 100644 --- a/src/tokens/Datatoken.ts +++ b/src/tokens/Datatoken.ts @@ -18,7 +18,8 @@ import { ConsumeMarketFee, FreOrderParams, FreCreationParams, - ProviderFees + ProviderFees, + PublishingMarketFee } from '../@types' import { Nft } from './NFT' import { Config } from '../models/index.js' @@ -1311,4 +1312,102 @@ export class Datatoken { const balance = await dtContract.methods.balanceOf(address).call() return this.web3.utils.fromWei(balance) } + + /** + * @dev estGasSetPublishingMarketFee + * Estimating gas for publishMarketFeeAddress method + * @param {string} datatokenAddress Datatoken adress + * @param {string} publishMarketFeeAddress new publish Market Fee Address + * @param {string} publishMarketFeeToken new publish Market Fee Token + * @param {string} publishMarketFeeAmount new fee amount + * @param {String} address user adress + */ + public async estGasSetPublishingMarketFee( + datatokenAddress: string, + publishMarketFeeAddress: string, + publishMarketFeeToken: string, + publishMarketFeeAmount: string, + address: string + ): Promise { + // Estimate gas cost for publishMarketFeeAddress method + const dtContract = new this.web3.eth.Contract(this.datatokensAbi, datatokenAddress, { + from: address + }) + return estimateGas( + address, + dtContract.methods.setPublishingMarketFee, + publishMarketFeeAddress, + publishMarketFeeToken, + publishMarketFeeAmount + ) + } + + /** + * @dev setPublishingMarketFee + * Only publishMarketFeeAddress can call it + * This function allows to set the fee required by the publisherMarket + * @param {string} datatokenAddress Datatoken adress + * @param {string} publishMarketFeeAddress new publish Market Fee Address + * @param {string} publishMarketFeeToken new publish Market Fee Token + * @param {string} publishMarketFeeAmount new fee amount + * @param {String} address user adress + */ + public async setPublishingMarketFee( + datatokenAddress: string, + publishMarketFeeAddress: string, + publishMarketFeeToken: string, + publishMarketFeeAmount: string, + address: string + ) { + const dtContract = new this.web3.eth.Contract(this.datatokensAbi, datatokenAddress, { + from: address + }) + const mktFeeAddress = (await dtContract.methods.getPublishingMarketFee().call())[0] + if (mktFeeAddress !== address) { + throw new Error(`Caller is not the Publishing Market Fee Address`) + } + const estGas = await this.estGasSetPublishingMarketFee( + datatokenAddress, + publishMarketFeeAddress, + publishMarketFeeToken, + publishMarketFeeAmount, + address + ) + await dtContract.methods + .setPublishingMarketFee( + publishMarketFeeAddress, + publishMarketFeeToken, + publishMarketFeeAmount + ) + .send({ + from: address, + gas: estGas + 1, + gasPrice: await getFairGasPrice(this.web3, this.config) + }) + } + + /** + * @dev getPublishingMarketFee + * Get publishingMarket Fee + * This function allows to get the current fee set by the publishing market + * @param {String} datatokenAddress Datatoken adress + * @param {String} address user adress + * @return {Promise} Current fee set by the publishing market + */ + public async getPublishingMarketFee( + datatokenAddress: string, + address: string + ): Promise { + const dtContract = new this.web3.eth.Contract(this.datatokensAbi, datatokenAddress, { + from: address + }) + + const publishingMarketFee = await dtContract.methods.getPublishingMarketFee().call() + const returnValues = { + publishMarketFeeAddress: publishingMarketFee[0], + publishMarketFeeToken: publishingMarketFee[1], + publishMarketFeeAmount: publishingMarketFee[2] + } + return returnValues + } } diff --git a/test/unit/pools/Router.test.ts b/test/unit/pools/Router.test.ts index b4f1db47..8a297a05 100644 --- a/test/unit/pools/Router.test.ts +++ b/test/unit/pools/Router.test.ts @@ -3,8 +3,14 @@ import { AbiItem } from 'web3-utils/types' import { deployContracts, Addresses } from '../../TestContractHandler' import MockERC20 from '@oceanprotocol/contracts/artifacts/contracts/utils/mock/MockERC20Decimals.sol/MockERC20Decimals.json' import { web3 } from '../../config' -import { NftFactory, NftCreateData, balance, approve, ZERO_ADDRESS } from '../../../src' -import { Router } from '../../../src/pools/Router' +import { + NftFactory, + NftCreateData, + Router, + balance, + approve, + ZERO_ADDRESS +} from '../../../src' import { Erc20CreateParams, PoolCreationParams, Operation } from '../../../src/@types' const { keccak256 } = require('@ethersproject/keccak256') diff --git a/test/unit/pools/dispenser/Dispenser.test.ts b/test/unit/pools/dispenser/Dispenser.test.ts index 08aa72fd..9c8323a1 100644 --- a/test/unit/pools/dispenser/Dispenser.test.ts +++ b/test/unit/pools/dispenser/Dispenser.test.ts @@ -1,7 +1,4 @@ -import { AbiItem } from 'web3-utils' import { assert, expect } from 'chai' -import ERC20Template from '@oceanprotocol/contracts/artifacts/contracts/templates/ERC20Template.sol/ERC20Template.json' -import DispenserTemplate from '@oceanprotocol/contracts/artifacts/contracts/pools/dispenser/Dispenser.sol/Dispenser.json' import { deployContracts, Addresses } from '../../../TestContractHandler' import { web3 } from '../../../config' import { @@ -9,31 +6,52 @@ import { NftCreateData, Datatoken, DispenserParams, - Dispenser + Dispenser, + ZERO_ADDRESS } from '../../../../src/' import { Erc20CreateParams } from '../../../../src/@types' describe('Dispenser flow', () => { let factoryOwner: string - let nftOwner: string let user1: string let user2: string - let user3: string let contracts: Addresses - let DispenserAddress: string let DispenserClass: Dispenser let nftFactory: NftFactory let datatoken: Datatoken - let nftAddress: string let dtAddress: string + const nftData: NftCreateData = { + name: '72120Bundle', + symbol: '72Bundle', + templateIndex: 1, + tokenURI: 'https://oceanprotocol.com/nft/', + transferable: true, + owner: null + } + + const ercParams: Erc20CreateParams = { + templateIndex: 1, + minter: null, + paymentCollector: null, + mpFeeAddress: null, + feeToken: ZERO_ADDRESS, + cap: '1000000', + feeAmount: '0', + name: 'ERC20B1', + symbol: 'ERC20DT1Symbol' + } + before(async () => { const accounts = await web3.eth.getAccounts() factoryOwner = accounts[0] - nftOwner = accounts[1] - user1 = accounts[2] - user2 = accounts[3] - user3 = accounts[4] + user1 = accounts[3] + user2 = accounts[4] + + nftData.owner = factoryOwner + ercParams.minter = factoryOwner + ercParams.paymentCollector = user2 + ercParams.mpFeeAddress = user1 }) it('should deploy contracts', async () => { @@ -41,39 +59,13 @@ describe('Dispenser flow', () => { }) it('should initialize Dispenser class', async () => { - DispenserClass = new Dispenser( - web3, - 8996, - contracts.dispenserAddress, - DispenserTemplate.abi as AbiItem[] - ) + DispenserClass = new Dispenser(web3, 8996, contracts.dispenserAddress) assert(DispenserClass !== null) }) it('#createNftwithErc - should create an NFT and a Datatoken ', async () => { nftFactory = new NftFactory(contracts.erc721FactoryAddress, web3) - const nftData: NftCreateData = { - name: '72120Bundle', - symbol: '72Bundle', - templateIndex: 1, - tokenURI: 'https://oceanprotocol.com/nft/', - transferable: true, - owner: factoryOwner - } - - const ercParams: Erc20CreateParams = { - templateIndex: 1, - minter: factoryOwner, - paymentCollector: user3, - mpFeeAddress: user2, - feeToken: '0x0000000000000000000000000000000000000000', - cap: '10000', - feeAmount: '0', - name: 'ERC20B1', - symbol: 'ERC20DT1Symbol' - } - const txReceipt = await nftFactory.createNftWithErc20( factoryOwner, nftData, @@ -83,12 +75,11 @@ describe('Dispenser flow', () => { expect(txReceipt.events.NFTCreated.event === 'NFTCreated') expect(txReceipt.events.TokenCreated.event === 'TokenCreated') - nftAddress = txReceipt.events.NFTCreated.returnValues.newTokenAddress dtAddress = txReceipt.events.TokenCreated.returnValues.newTokenAddress }) it('Make user2 minter', async () => { - datatoken = new Datatoken(web3, 8996, ERC20Template.abi as AbiItem[]) + datatoken = new Datatoken(web3, 8996) await datatoken.addMinter(dtAddress, factoryOwner, user2) assert((await datatoken.getDTPermissions(dtAddress, user2)).minter === true) }) @@ -113,38 +104,38 @@ describe('Dispenser flow', () => { assert(tx, 'Cannot activate dispenser') }) - it('user2 gets the dispenser status', async () => { + it('user1 gets the dispenser status', async () => { const status = await DispenserClass.status(dtAddress) assert(status.active === true, 'Dispenser not active') assert(status.owner === factoryOwner, 'Dispenser owner is not alice') assert(status.isMinter === true, 'Dispenser is not a minter') }) - it('user2 deactivates the dispenser', async () => { + it('user1 deactivates the dispenser', async () => { const tx = await DispenserClass.deactivate(dtAddress, factoryOwner) assert(tx, 'Cannot deactivate dispenser') const status = await DispenserClass.status(dtAddress) assert(status.active === false, 'Dispenser is still active') }) - it('user2 sets user3 as an AllowedSwapper for the dispenser', async () => { - const tx = await DispenserClass.setAllowedSwapper(dtAddress, factoryOwner, user3) + it('user1 sets user2 as an AllowedSwapper for the dispenser', async () => { + const tx = await DispenserClass.setAllowedSwapper(dtAddress, factoryOwner, user2) assert(tx, 'Cannot set Allowed Swapper') const status = await DispenserClass.status(dtAddress) - assert(status.allowedSwapper === user3, 'user3 is Allowed Swapper') + assert(status.allowedSwapper === user2, 'user2 is Allowed Swapper') }) - it('User3 requests datatokens', async () => { - const activate = await DispenserClass.activate(dtAddress, '10', '10', factoryOwner) - const check = await DispenserClass.isDispensable(dtAddress, datatoken, user3, '1') + it('user2 requests datatokens', async () => { + await DispenserClass.activate(dtAddress, '10', '10', factoryOwner) + const check = await DispenserClass.isDispensable(dtAddress, datatoken, user2, '1') assert(check === true, 'isDispensable should return true') - const tx = await DispenserClass.dispense(dtAddress, user3, '1', user3) - assert(tx, 'user3 failed to get 1DT') + const tx = await DispenserClass.dispense(dtAddress, user2, '1', user2) + assert(tx, 'user2 failed to get 1DT') }) - it('user2 withdraws all datatokens', async () => { + it('user1 withdraws all datatokens', async () => { const tx = await DispenserClass.ownerWithdraw(dtAddress, factoryOwner) - assert(tx, 'user2 failed to withdraw all her tokens') + assert(tx, 'user1 failed to withdraw all her tokens') const status = await DispenserClass.status(dtAddress) assert(status.balance === '0', 'Balance > 0') }) diff --git a/test/unit/pools/ssContracts/SideStaking.test.ts b/test/unit/pools/ssContracts/SideStaking.test.ts index d9efdebd..687df98d 100644 --- a/test/unit/pools/ssContracts/SideStaking.test.ts +++ b/test/unit/pools/ssContracts/SideStaking.test.ts @@ -1,9 +1,8 @@ import { assert, expect } from 'chai' import { AbiItem } from 'web3-utils/types' import { Contract } from 'web3-eth-contract' -import SSContract from '@oceanprotocol/contracts/artifacts/contracts/pools/ssContracts/SideStaking.sol/SideStaking.json' +import BigNumber from 'bignumber.js' import ERC20Template from '@oceanprotocol/contracts/artifacts/contracts/templates/ERC20Template.sol/ERC20Template.json' -import PoolTemplate from '@oceanprotocol/contracts/artifacts/contracts/pools/balancer/BPool.sol/BPool.json' import MockERC20 from '@oceanprotocol/contracts/artifacts/contracts/utils/mock/MockERC20Decimals.sol/MockERC20Decimals.json' import { deployContracts, Addresses } from '../../../TestContractHandler' import { web3 } from '../../../config' @@ -14,9 +13,10 @@ import { NftFactory, NftCreateData, Pool, - unitsToAmount + SideStaking, + unitsToAmount, + ZERO_ADDRESS } from '../../../../src' -import { SideStaking } from '../../../../src/pools/ssContracts/SideStaking' import { Erc20CreateParams, PoolCreationParams, @@ -27,86 +27,108 @@ import { describe('SideStaking unit test', () => { let factoryOwner: string - let nftOwner: string let user1: string let user2: string - let user3: string let initialBlock: number - let sideStakingAddress: string let contracts: Addresses let pool: Pool let sideStaking: SideStaking - let dtAddress: string - let dtAddress2: string let poolAddress: string let erc20Token: string let erc20Contract: Contract let daiContract: Contract let usdcContract: Contract - const vestedBlocks = 2500000 + + const VESTED_BLOCKS = 2500000 + const VESTING_AMOUNT = '10000' + const BASE_TOKEN_LIQUIDITY = 2000 + + const nftData: NftCreateData = { + name: '72120Bundle', + symbol: '72Bundle', + templateIndex: 1, + tokenURI: 'https://oceanprotocol.com/nft/', + transferable: true, + owner: null + } + + const ercParams: Erc20CreateParams = { + templateIndex: 1, + minter: null, + paymentCollector: null, + mpFeeAddress: null, + feeToken: ZERO_ADDRESS, + cap: '1000000', + feeAmount: '0', + name: 'ERC20B1', + symbol: 'ERC20DT1Symbol' + } before(async () => { const accounts = await web3.eth.getAccounts() factoryOwner = accounts[0] - nftOwner = accounts[1] - user1 = accounts[2] - user2 = accounts[3] - user3 = accounts[4] + user1 = accounts[1] + user2 = accounts[2] + + nftData.owner = factoryOwner + ercParams.minter = factoryOwner + ercParams.paymentCollector = user2 + ercParams.mpFeeAddress = factoryOwner }) it('should deploy contracts', async () => { contracts = await deployContracts(web3, factoryOwner) - sideStakingAddress = contracts.sideStakingAddress // initialize Pool instance - pool = new Pool(web3, 8996, PoolTemplate.abi as AbiItem[]) + pool = new Pool(web3, 8996) assert(pool != null) // - sideStaking = new SideStaking(web3, 8996, SSContract.abi as AbiItem[]) + sideStaking = new SideStaking(web3, 8996) assert(sideStaking != null) daiContract = new web3.eth.Contract(MockERC20.abi as AbiItem[], contracts.daiAddress) - usdcContract = new web3.eth.Contract( MockERC20.abi as AbiItem[], contracts.usdcAddress ) + await approve( web3, factoryOwner, contracts.daiAddress, contracts.erc721FactoryAddress, - '2000' + BASE_TOKEN_LIQUIDITY.toString() ) + + assert( + parseInt( + await allowance( + web3, + contracts.daiAddress, + factoryOwner, + contracts.erc721FactoryAddress + ) + ) >= BASE_TOKEN_LIQUIDITY + ) + await approve( web3, factoryOwner, contracts.usdcAddress, contracts.erc721FactoryAddress, - '10000' + BASE_TOKEN_LIQUIDITY.toString() ) - let allowCheck = await allowance( - web3, - contracts.daiAddress, - factoryOwner, - contracts.erc721FactoryAddress + assert( + parseInt( + await allowance( + web3, + contracts.usdcAddress, + factoryOwner, + contracts.erc721FactoryAddress + ) + ) >= BASE_TOKEN_LIQUIDITY ) - assert(parseInt(allowCheck) >= 2000) - allowCheck = await allowance( - web3, - contracts.usdcAddress, - factoryOwner, - contracts.erc721FactoryAddress - ) - assert(parseInt(allowCheck) >= 10000) - - console.log( - await usdcContract.methods.decimals().call(), - 'USDC DECIMALS IN THIS TEST' - ) - - await amountToUnits(web3, contracts.usdcAddress, '20') }) describe('Test a pool with DAI (18 Decimals)', () => { @@ -115,27 +137,6 @@ describe('SideStaking unit test', () => { // we prepare transaction parameters objects const nftFactory = new NftFactory(contracts.erc721FactoryAddress, web3) - const nftData: NftCreateData = { - name: '72120Bundle', - symbol: '72Bundle', - templateIndex: 1, - tokenURI: 'https://oceanprotocol.com/nft/', - transferable: true, - owner: factoryOwner - } - - const ercParams: Erc20CreateParams = { - templateIndex: 1, - minter: factoryOwner, - paymentCollector: user3, - mpFeeAddress: factoryOwner, - feeToken: '0x0000000000000000000000000000000000000000', - cap: '1000000', - feeAmount: '0', - name: 'ERC20B1', - symbol: 'ERC20DT1Symbol' - } - const poolParams: PoolCreationParams = { ssContract: contracts.sideStakingAddress, baseTokenAddress: contracts.daiAddress, @@ -145,9 +146,9 @@ describe('SideStaking unit test', () => { poolTemplateAddress: contracts.poolTemplateAddress, rate: '1', baseTokenDecimals: 18, - vestingAmount: '10000', - vestedBlocks: vestedBlocks, - initialBaseTokenLiquidity: '2000', + vestingAmount: VESTING_AMOUNT, + vestedBlocks: VESTED_BLOCKS, + initialBaseTokenLiquidity: BASE_TOKEN_LIQUIDITY.toString(), swapFeeLiquidityProvider: '0.001', swapFeeMarketRunner: '0.001' } @@ -164,13 +165,12 @@ describe('SideStaking unit test', () => { poolAddress = txReceipt.events.NewPool.returnValues.poolAddress erc20Contract = new web3.eth.Contract(ERC20Template.abi as AbiItem[], erc20Token) - // user2 has no dt1 - expect(await erc20Contract.methods.balanceOf(user2).call()).to.equal('0') - - sideStakingAddress = contracts.sideStakingAddress + // user1 has no dt1 + expect(await erc20Contract.methods.balanceOf(user1).call()).to.equal('0') }) + it('#getRouter - should get Router address', async () => { - expect(await sideStaking.getRouter(sideStakingAddress)).to.equal( + expect(await sideStaking.getRouter(contracts.sideStakingAddress)).to.equal( contracts.routerAddress ) }) @@ -181,69 +181,87 @@ describe('SideStaking unit test', () => { contracts.sideStakingAddress, erc20Token ) - ).to.equal(web3.utils.toWei('2000')) + ).to.equal(web3.utils.toWei(BASE_TOKEN_LIQUIDITY.toString())) }) + it('#getDatatokenCurrentCirculatingSupply - should get datatoken supply in circulation ', async () => { expect( await sideStaking.getDatatokenCurrentCirculatingSupply( contracts.sideStakingAddress, erc20Token ) - ).to.equal(web3.utils.toWei('2000')) + ).to.equal(web3.utils.toWei(BASE_TOKEN_LIQUIDITY.toString())) }) + it('#getBaseToken - should get baseToken address', async () => { - expect(await sideStaking.getBaseToken(sideStakingAddress, erc20Token)).to.equal( - contracts.daiAddress - ) + expect( + await sideStaking.getBaseToken(contracts.sideStakingAddress, erc20Token) + ).to.equal(contracts.daiAddress) }) + it('#getPoolAddress - should get pool address', async () => { - expect(await sideStaking.getPoolAddress(sideStakingAddress, erc20Token)).to.equal( - poolAddress - ) + expect( + await sideStaking.getPoolAddress(contracts.sideStakingAddress, erc20Token) + ).to.equal(poolAddress) }) + it('#getPublisherAddress - should get publisher address', async () => { expect( - await sideStaking.getPublisherAddress(sideStakingAddress, erc20Token) + await sideStaking.getPublisherAddress(contracts.sideStakingAddress, erc20Token) ).to.equal(factoryOwner) }) + it('#getBaseTokenBalance ', async () => { expect( - await sideStaking.getBaseTokenBalance(sideStakingAddress, erc20Token) + await sideStaking.getBaseTokenBalance(contracts.sideStakingAddress, erc20Token) ).to.equal('0') }) - // it('#getDatatokenBalance ', async () => { - // expect( - // await sideStaking.getDatatokenBalance(sideStakingAddress, erc20Token) - // ).to.equal('997999.9999999999') - // }) - it('#getvestingAmount ', async () => { - expect(await sideStaking.getvestingAmount(sideStakingAddress, erc20Token)).to.equal( - '0' + it('#getDatatokenBalance ', async () => { + expect( + await ( + await sideStaking.getDatatokenBalance(contracts.sideStakingAddress, erc20Token) + ).toString() + ).to.equal( + new BigNumber(2) + .exponentiatedBy(256) + .minus(1) + .dividedBy(new BigNumber(10).exponentiatedBy(18)) + .minus(BASE_TOKEN_LIQUIDITY) + .toString() ) }) + + it('#getvestingAmount ', async () => { + expect( + await sideStaking.getvestingAmount(contracts.sideStakingAddress, erc20Token) + ).to.equal('0') + }) + it('#getvestingLastBlock ', async () => { expect( - await sideStaking.getvestingLastBlock(sideStakingAddress, erc20Token) + await sideStaking.getvestingLastBlock(contracts.sideStakingAddress, erc20Token) ).to.equal(initialBlock.toString()) }) it('#getvestingAmountSoFar ', async () => { expect( - await sideStaking.getvestingAmountSoFar(sideStakingAddress, erc20Token) + await sideStaking.getvestingAmountSoFar(contracts.sideStakingAddress, erc20Token) ).to.equal('0') }) it('#swapExactAmountIn - should swap', async () => { await daiContract.methods - .transfer(user2, web3.utils.toWei('1000')) + .transfer(user1, web3.utils.toWei('1000')) .send({ from: factoryOwner }) - await approve(web3, user2, contracts.daiAddress, poolAddress, '10') + await approve(web3, user1, contracts.daiAddress, poolAddress, '10') + const tokenInOutMarket: TokenInOutMarket = { tokenIn: contracts.daiAddress, tokenOut: erc20Token, marketFeeAddress: factoryOwner } + const amountsInOutMaxFee: AmountsInMaxFee = { tokenAmountIn: '10', minAmountOut: '1', @@ -251,18 +269,19 @@ describe('SideStaking unit test', () => { } const tx = await pool.swapExactAmountIn( - user2, + user1, poolAddress, tokenInOutMarket, amountsInOutMaxFee ) - expect(await erc20Contract.methods.balanceOf(user2).call()).to.equal( + + expect(await erc20Contract.methods.balanceOf(user1).call()).to.equal( tx.events.LOG_SWAP.returnValues.tokenAmountOut ) }) it('#swapExactAmountOut - should swap', async () => { - await approve(web3, user2, contracts.daiAddress, poolAddress, '100') + await approve(web3, user1, contracts.daiAddress, poolAddress, '100') const tokenInOutMarket: TokenInOutMarket = { tokenIn: contracts.daiAddress, tokenOut: erc20Token, @@ -274,7 +293,7 @@ describe('SideStaking unit test', () => { swapMarketFee: '0.1' } const tx = await pool.swapExactAmountOut( - user2, + user1, poolAddress, tokenInOutMarket, amountsInOutMaxFee @@ -282,15 +301,15 @@ describe('SideStaking unit test', () => { assert(tx != null) }) - it('#joinswapExternAmountIn- user2 should add liquidity, receiving LP tokens', async () => { + it('#joinswapExternAmountIn- user1 should add liquidity, receiving LP tokens', async () => { const daiAmountIn = '100' const minBPTOut = '0.1' - await approve(web3, user2, contracts.daiAddress, poolAddress, '100', true) - expect(await allowance(web3, contracts.daiAddress, user2, poolAddress)).to.equal( + await approve(web3, user1, contracts.daiAddress, poolAddress, '100', true) + expect(await allowance(web3, contracts.daiAddress, user1, poolAddress)).to.equal( '100' ) const tx = await pool.joinswapExternAmountIn( - user2, + user1, poolAddress, daiAmountIn, minBPTOut @@ -306,12 +325,12 @@ describe('SideStaking unit test', () => { ) }) - it('#exitswapPoolAmountIn- user2 exit the pool receiving only DAI', async () => { + it('#exitswapPoolAmountIn- user1 exit the pool receiving only DAI', async () => { const BPTAmountIn = '0.5' const minDAIOut = '0.5' const tx = await pool.exitswapPoolAmountIn( - user2, + user1, poolAddress, BPTAmountIn, minDAIOut @@ -332,27 +351,6 @@ describe('SideStaking unit test', () => { // we prepare transaction parameters objects const nftFactory = new NftFactory(contracts.erc721FactoryAddress, web3) - const nftData: NftCreateData = { - name: '72120Bundle', - symbol: '72Bundle', - templateIndex: 1, - tokenURI: 'https://oceanprotocol.com/nft/', - transferable: true, - owner: factoryOwner - } - - const ercParams: Erc20CreateParams = { - templateIndex: 1, - minter: factoryOwner, - paymentCollector: user3, - mpFeeAddress: factoryOwner, - feeToken: '0x0000000000000000000000000000000000000000', - cap: '1000000', - feeAmount: '0', - name: 'ERC20B1', - symbol: 'ERC20DT1Symbol' - } - const poolParams: PoolCreationParams = { ssContract: contracts.sideStakingAddress, baseTokenAddress: contracts.usdcAddress, @@ -362,12 +360,16 @@ describe('SideStaking unit test', () => { poolTemplateAddress: contracts.poolTemplateAddress, rate: '1', baseTokenDecimals: await usdcContract.methods.decimals().call(), - vestingAmount: '10000', - vestedBlocks: 2500000, + vestingAmount: VESTING_AMOUNT, + vestedBlocks: VESTED_BLOCKS, initialBaseTokenLiquidity: await unitsToAmount( web3, contracts.usdcAddress, - await amountToUnits(web3, contracts.usdcAddress, '2000') + await amountToUnits( + web3, + contracts.usdcAddress, + BASE_TOKEN_LIQUIDITY.toString() + ) ), swapFeeLiquidityProvider: '0.001', swapFeeMarketRunner: '0.001' @@ -385,45 +387,56 @@ describe('SideStaking unit test', () => { poolAddress = txReceipt.events.NewPool.returnValues.poolAddress erc20Contract = new web3.eth.Contract(ERC20Template.abi as AbiItem[], erc20Token) - // user2 has no dt1 - expect(await erc20Contract.methods.balanceOf(user2).call()).to.equal('0') + // user1 has no dt1 + expect(await erc20Contract.methods.balanceOf(user1).call()).to.equal('0') }) it('#getBaseTokenBalance ', async () => { expect( - await sideStaking.getBaseTokenBalance(sideStakingAddress, erc20Token) + await sideStaking.getBaseTokenBalance(contracts.sideStakingAddress, erc20Token) ).to.equal('0') }) - // it('#getDatatokenBalance ', async () => { - // expect( - // await sideStaking.getDatatokenBalance(sideStakingAddress, erc20Token) - // ).to.equal('997999.9999999999') - // }) - it('#getvestingAmount ', async () => { - expect(await sideStaking.getvestingAmount(sideStakingAddress, erc20Token)).to.equal( - '0' + it('#getDatatokenBalance ', async () => { + expect( + await ( + await sideStaking.getDatatokenBalance(contracts.sideStakingAddress, erc20Token) + ).toString() + ).to.equal( + new BigNumber(2) + .exponentiatedBy(256) + .minus(1) + .dividedBy(new BigNumber(10).exponentiatedBy(18)) + .minus(BASE_TOKEN_LIQUIDITY) + .toString() ) }) + + it('#getvestingAmount ', async () => { + expect( + await sideStaking.getvestingAmount(contracts.sideStakingAddress, erc20Token) + ).to.equal('0') + }) + it('#getvestingLastBlock ', async () => { expect( - await sideStaking.getvestingLastBlock(sideStakingAddress, erc20Token) + await sideStaking.getvestingLastBlock(contracts.sideStakingAddress, erc20Token) ).to.equal(initialBlock.toString()) }) it('#getvestingAmountSoFar ', async () => { expect( - await sideStaking.getvestingAmountSoFar(sideStakingAddress, erc20Token) + await sideStaking.getvestingAmountSoFar(contracts.sideStakingAddress, erc20Token) ).to.equal('0') }) it('#swapExactAmountIn - should swap', async () => { const transferAmount = await amountToUnits(web3, contracts.usdcAddress, '1000') // 1000 USDC await usdcContract.methods - .transfer(user2, transferAmount) + .transfer(user1, transferAmount) .send({ from: factoryOwner }) - await approve(web3, user2, contracts.usdcAddress, poolAddress, '10') + await approve(web3, user1, contracts.usdcAddress, poolAddress, '10') const tokenInOutMarket: TokenInOutMarket = { tokenIn: contracts.usdcAddress, tokenOut: erc20Token, @@ -435,18 +448,18 @@ describe('SideStaking unit test', () => { swapMarketFee: '0.1' } const tx = await pool.swapExactAmountIn( - user2, + user1, poolAddress, tokenInOutMarket, amountsInOutMaxFee ) - expect(await erc20Contract.methods.balanceOf(user2).call()).to.equal( + expect(await erc20Contract.methods.balanceOf(user1).call()).to.equal( tx.events.LOG_SWAP.returnValues.tokenAmountOut ) }) it('#swapExactAmountOut - should swap', async () => { - await approve(web3, user2, contracts.usdcAddress, poolAddress, '100') + await approve(web3, user1, contracts.usdcAddress, poolAddress, '100') const tokenInOutMarket: TokenInOutMarket = { tokenIn: contracts.usdcAddress, tokenOut: erc20Token, @@ -458,22 +471,21 @@ describe('SideStaking unit test', () => { swapMarketFee: '0.1' } const tx = await pool.swapExactAmountOut( - user2, + user1, poolAddress, tokenInOutMarket, amountsInOutMaxFee ) assert(tx != null) - // console.log(tx.events) }) - it('#joinswapExternAmountIn- user2 should add liquidity, receiving LP tokens', async () => { + it('#joinswapExternAmountIn- user1 should add liquidity, receiving LP tokens', async () => { const usdcAmountIn = '100' const minBPTOut = '0.1' - await approve(web3, user2, contracts.usdcAddress, poolAddress, '100', true) + await approve(web3, user1, contracts.usdcAddress, poolAddress, '100', true) const tx = await pool.joinswapExternAmountIn( - user2, + user1, poolAddress, usdcAmountIn, minBPTOut @@ -489,12 +501,12 @@ describe('SideStaking unit test', () => { ) }) - it('#exitswapPoolAmountIn- user2 exit the pool receiving only USDC', async () => { + it('#exitswapPoolAmountIn- user1 exit the pool receiving only USDC', async () => { const BPTAmountIn = '0.5' const minUSDCOut = '0.5' const tx = await pool.exitswapPoolAmountIn( - user2, + user1, poolAddress, BPTAmountIn, minUSDCOut diff --git a/test/unit/tokens/Datatoken.test.ts b/test/unit/tokens/Datatoken.test.ts index 78eb9781..226b87da 100644 --- a/test/unit/tokens/Datatoken.test.ts +++ b/test/unit/tokens/Datatoken.test.ts @@ -1,11 +1,5 @@ import { assert } from 'chai' -import ERC20TemplateEnterprise from '@oceanprotocol/contracts/artifacts/contracts/templates/ERC20TemplateEnterprise.sol/ERC20TemplateEnterprise.json' -import ERC721Factory from '@oceanprotocol/contracts/artifacts/contracts/ERC721Factory.sol/ERC721Factory.json' -import ERC721Template from '@oceanprotocol/contracts/artifacts/contracts/templates/ERC721Template.sol/ERC721Template.json' -import ERC20Template from '@oceanprotocol/contracts/artifacts/contracts/templates/ERC20Template.sol/ERC20Template.json' -import MockERC20 from '@oceanprotocol/contracts/artifacts/contracts/utils/mock/MockERC20Decimals.sol/MockERC20Decimals.json' import { deployContracts, Addresses } from '../../TestContractHandler' -import { AbiItem } from 'web3-utils' import { web3 } from '../../config' import { NftFactory, @@ -17,7 +11,7 @@ import { ZERO_ADDRESS, signHash } from '../../../src' -import { ProviderFees, FreCreationParams, FreOrderParams } from '../../../src/@types/' +import { ProviderFees, FreCreationParams, FreOrderParams } from '../../../src/@types' describe('Datatoken', () => { let nftOwner: string @@ -33,9 +27,16 @@ describe('Datatoken', () => { let datatokenAddress: string let fixedRateAddress: string let exchangeId: string + let freParams: FreCreationParams - const nftName = 'NFTName' - const nftSymbol = 'NFTSymbol' + const nftData: NftCreateData = { + name: 'NFTName', + symbol: 'NFTSymbol', + templateIndex: 1, + tokenURI: 'https://oceanprotocol.com/nft/', + transferable: true, + owner: null + } before(async () => { const accounts = await web3.eth.getAccounts() @@ -44,38 +45,30 @@ describe('Datatoken', () => { user2 = accounts[2] user3 = accounts[3] erc20DeployerUser = accounts[4] + + nftData.owner = nftOwner }) it('should deploy contracts', async () => { contracts = await deployContracts(web3, nftOwner) - const daiContract = new web3.eth.Contract( - MockERC20.abi as AbiItem[], - contracts.daiAddress - ) - await daiContract.methods - .approve(contracts.erc721FactoryAddress, web3.utils.toWei('10000')) - .send({ from: nftOwner }) + freParams = { + fixedRateAddress: contracts.fixedRateAddress, + baseTokenAddress: contracts.daiAddress, + owner: nftOwner, + marketFeeCollector: nftOwner, + baseTokenDecimals: 18, + datatokenDecimals: 18, + fixedRate: web3.utils.toWei('1'), + marketFee: '0' + } }) it('should initialize NFTFactory instance and create a new NFT', async () => { - nftFactory = new NftFactory( - contracts.erc721FactoryAddress, - web3, - 8996, - ERC721Factory.abi as AbiItem[] - ) - const nftData: NftCreateData = { - name: nftName, - symbol: nftSymbol, - templateIndex: 1, - tokenURI: 'https://oceanprotocol.com/nft/', - transferable: true, - owner: nftOwner - } + nftFactory = new NftFactory(contracts.erc721FactoryAddress, web3, 8996) nftAddress = await nftFactory.createNFT(nftOwner, nftData) - nftDatatoken = new Nft(web3, 8996, ERC721Template.abi as AbiItem[]) + nftDatatoken = new Nft(web3, 8996) }) it('#createERC20 - should create a new ERC20 DT from NFT contract', async () => { @@ -86,29 +79,24 @@ describe('Datatoken', () => { nftOwner, user1, user2, - '0x0000000000000000000000000000000000000000', + ZERO_ADDRESS, '0', '10000', - nftName, - nftSymbol, - 1 + 'ERC20B1', + 'ERC20DT1Symbol' ) assert(datatokenAddress !== null) }) it('should initialize DT20 Instance', async () => { - datatoken = new Datatoken( - web3, - 8996, - ERC20Template.abi as AbiItem[], - ERC20TemplateEnterprise.abi as AbiItem[] - ) + datatoken = new Datatoken(web3, 8996) }) it('#mint - should fail to mint DT20, if NOT Minter', async () => { - // assert((await datatoken.getDTPermissions(datatokenAddress, user1)).minter === false) + assert((await datatoken.getDTPermissions(datatokenAddress, user1)).minter === false) try { await datatoken.mint(datatokenAddress, user1, '10', user1) + assert(false) } catch (e) { assert(e.message === 'Caller is not Minter') } @@ -129,6 +117,7 @@ describe('Datatoken', () => { try { await datatoken.addMinter(datatokenAddress, user3, user2) + assert(false) } catch (e) { assert(e.message === 'Caller is not ERC20Deployer') } @@ -144,16 +133,6 @@ describe('Datatoken', () => { }) it('#createFixedRate - should create FRE for the erc20 dt', async () => { - const freParams: FreCreationParams = { - fixedRateAddress: contracts.fixedRateAddress, - baseTokenAddress: contracts.daiAddress, - owner: nftOwner, - marketFeeCollector: nftOwner, - baseTokenDecimals: 18, - datatokenDecimals: 18, - fixedRate: web3.utils.toWei('1'), - marketFee: '0' - } const fre = await datatoken.createFixedRate(datatokenAddress, nftOwner, freParams) assert(fre !== null) fixedRateAddress = fre.events.NewFixedRate.address @@ -162,18 +141,9 @@ describe('Datatoken', () => { it('#createFixedRate - should FAIL create FRE if NOT ERC20Deployer', async () => { assert((await nftDatatoken.isErc20Deployer(nftAddress, user3)) === false) - const freParams: FreCreationParams = { - fixedRateAddress: contracts.fixedRateAddress, - baseTokenAddress: contracts.daiAddress, - owner: nftOwner, - marketFeeCollector: nftOwner, - baseTokenDecimals: 18, - datatokenDecimals: 18, - fixedRate: web3.utils.toWei('1'), - marketFee: '0' - } try { await datatoken.createFixedRate(datatokenAddress, user3, freParams) + assert(false) } catch (e) { assert(e.message === 'User is not ERC20 Deployer') } @@ -207,6 +177,7 @@ describe('Datatoken', () => { contracts.dispenserAddress, dispenserParams ) + assert(false) } catch (e) { assert(e.message === 'User is not ERC20 Deployer') } @@ -218,6 +189,7 @@ describe('Datatoken', () => { try { await datatoken.removeMinter(datatokenAddress, user2, user1) + assert(false) } catch (e) { assert(e.message === 'Caller is not ERC20Deployer') } @@ -241,6 +213,7 @@ describe('Datatoken', () => { try { await datatoken.addPaymentManager(datatokenAddress, user1, user2) + assert(false) } catch (e) { assert(e.message === 'Caller is not ERC20Deployer') } @@ -269,6 +242,7 @@ describe('Datatoken', () => { ) try { await datatoken.removePaymentManager(datatokenAddress, user1, user2) + assert(false) } catch (e) { assert(e.message === 'Caller is not ERC20Deployer') } @@ -298,6 +272,7 @@ describe('Datatoken', () => { try { await datatoken.setPaymentCollector(datatokenAddress, user1, user2) + assert(false) } catch (e) { assert(e.message === 'Caller is not Fee Manager, owner or erc20 Deployer') } @@ -435,7 +410,6 @@ describe('Datatoken', () => { const providerData = JSON.stringify({ timeout: 0 }) const providerFeeToken = ZERO_ADDRESS const providerFeeAmount = '0' - const dtAmount = web3.utils.toWei('1') const message = web3.utils.soliditySha3( { t: 'bytes', v: web3.utils.toHex(web3.utils.asciiToHex(providerData)) }, { t: 'address', v: user3 }, @@ -455,8 +429,8 @@ describe('Datatoken', () => { validUntil: providerValidUntil } const consumeMarketFee = { - consumeMarketFeeAddress: '0x0000000000000000000000000000000000000000', - consumeMarketFeeToken: '0x0000000000000000000000000000000000000000', + consumeMarketFeeAddress: ZERO_ADDRESS, + consumeMarketFeeToken: ZERO_ADDRESS, consumeMarketFeeAmount: '0' } const order: OrderParams = { @@ -497,8 +471,8 @@ describe('Datatoken', () => { validUntil: providerValidUntil } const consumeMarketFee = { - consumeMarketFeeAddress: '0x0000000000000000000000000000000000000000', - consumeMarketFeeToken: '0x0000000000000000000000000000000000000000', + consumeMarketFeeAddress: ZERO_ADDRESS, + consumeMarketFeeToken: ZERO_ADDRESS, consumeMarketFeeAmount: '0' } const order: OrderParams = { @@ -513,7 +487,7 @@ describe('Datatoken', () => { exchangeId: exchangeId, maxBaseTokenAmount: '1', swapMarketFee: '0.1', - marketFeeAddress: '0x0000000000000000000000000000000000000000' + marketFeeAddress: ZERO_ADDRESS } const buyTx = await datatoken.buyFromFreAndOrder(datatokenAddress, user1, order, fre) @@ -531,6 +505,7 @@ describe('Datatoken', () => { try { await datatoken.cleanPermissions(datatokenAddress, user2) + assert(false) } catch (e) { assert(e.message === 'Caller is NOT Nft Owner') } @@ -589,10 +564,91 @@ describe('Datatoken', () => { try { await datatoken.setData(datatokenAddress, user1, data) + assert(false) } catch (e) { assert(e.message === 'User is not ERC20 Deployer') } const key = web3.utils.keccak256(datatokenAddress) assert((await nftDatatoken.getData(nftAddress, key)) === OldData) }) + + it('#getDecimals - should return the number of decimals of the datatoken', async () => { + const decimals = await datatoken.getDecimals(datatokenAddress) + assert(decimals === '18') + }) + + it('#transfer - we can transfer the datatoken', async () => { + const balance1before = await datatoken.balance(datatokenAddress, user1) + const balance2before = await datatoken.balance(datatokenAddress, user2) + + await datatoken.transfer(datatokenAddress, user2, '1', user1) + + const balance1after = await datatoken.balance(datatokenAddress, user1) + const balance2after = await datatoken.balance(datatokenAddress, user2) + + assert(+balance1after === +balance1before - 1) + assert(+balance2after === +balance2before + 1) + }) + + it('#setPublishingMarketFee - User should not be able to set the Publishing Market Fee', async () => { + const originalPublishingMarketFee = await datatoken.getPublishingMarketFee( + datatokenAddress, + user1 + ) + try { + await datatoken.setPublishingMarketFee( + datatokenAddress, + user1, + contracts.daiAddress, + web3.utils.toWei('10'), + user1 + ) + } catch (e) { + console.log('Message:', e.message) + assert(e.message === 'Caller is not the Publishing Market Fee Address') + } + const newPublishingMarketFee = await datatoken.getPublishingMarketFee( + datatokenAddress, + user3 + ) + + assert( + newPublishingMarketFee.publishMarketFeeAddress === + originalPublishingMarketFee.publishMarketFeeAddress + ) + assert( + newPublishingMarketFee.publishMarketFeeAmount === + originalPublishingMarketFee.publishMarketFeeAmount + ) + assert( + newPublishingMarketFee.publishMarketFeeToken === + originalPublishingMarketFee.publishMarketFeeToken + ) + }) + it('#setPublishingMarketFee - Marketplace fee address should be able to set the Publishing Market Fee', async () => { + const originalPublishingMarketFee = await datatoken.getPublishingMarketFee( + datatokenAddress, + user2 + ) + try { + await datatoken.setPublishingMarketFee( + datatokenAddress, + user2, + contracts.daiAddress, + web3.utils.toWei('10'), + user2 + ) + } catch (e) { + console.log('Error:', e) + } + const newPublishingMarketFee = await datatoken.getPublishingMarketFee( + datatokenAddress, + user2 + ) + + assert(newPublishingMarketFee !== originalPublishingMarketFee) + assert(newPublishingMarketFee.publishMarketFeeAddress === user2) + assert(newPublishingMarketFee.publishMarketFeeAmount === web3.utils.toWei('10')) + assert(newPublishingMarketFee.publishMarketFeeToken === contracts.daiAddress) + }) }) diff --git a/test/unit/tokens/Nft.test.ts b/test/unit/tokens/Nft.test.ts index 42637886..4fd1b9ec 100644 --- a/test/unit/tokens/Nft.test.ts +++ b/test/unit/tokens/Nft.test.ts @@ -1,12 +1,9 @@ import { assert } from 'chai' -import ERC721Factory from '@oceanprotocol/contracts/artifacts/contracts/ERC721Factory.sol/ERC721Factory.json' -import ERC721Template from '@oceanprotocol/contracts/artifacts/contracts/templates/ERC721Template.sol/ERC721Template.json' import { deployContracts, Addresses } from '../../TestContractHandler' -import { AbiItem } from 'web3-utils' import sha256 from 'crypto-js/sha256' import { web3 } from '../../config' -import { NftFactory, NftCreateData, Nft } from '../../../src' -import { MetadataAndTokenURI } from '../../../src/@types/Erc721' +import { NftFactory, NftCreateData, Nft, ZERO_ADDRESS } from '../../../src' +import { MetadataAndTokenURI } from '../../../src/@types' describe('NFT', () => { let nftOwner: string @@ -18,10 +15,14 @@ describe('NFT', () => { let nftFactory: NftFactory let nftAddress: string - const nftName = 'NFTName' - const nftSymbol = 'NFTSymbol' - const publishMarketFeeAdress = '0xeE9300b7961e0a01d9f0adb863C7A227A07AaD75' - const oceanAddress = '0x967da4048cd07ab37855c090aaf366e4ce1b9f48' + const nftData: NftCreateData = { + name: 'NFTName', + symbol: 'NFTSymbol', + templateIndex: 1, + tokenURI: 'https://oceanprotocol.com/nft/', + transferable: true, + owner: null + } before(async () => { const accounts = await web3.eth.getAccounts() @@ -29,6 +30,8 @@ describe('NFT', () => { user1 = accounts[1] user2 = accounts[2] user3 = accounts[3] + + nftData.owner = nftOwner }) it('should deploy contracts', async () => { @@ -36,27 +39,15 @@ describe('NFT', () => { }) it('should initialize NFTFactory instance and create a new NFT', async () => { - nftFactory = new NftFactory( - contracts.erc721FactoryAddress, - web3, - 8996, - ERC721Factory.abi as AbiItem[] - ) - const nftData: NftCreateData = { - name: nftName, - symbol: nftSymbol, - templateIndex: 1, - tokenURI: 'https://oceanprotocol.com/nft/', - transferable: true, - owner: nftOwner - } + nftFactory = new NftFactory(contracts.erc721FactoryAddress, web3, 8996) nftAddress = await nftFactory.createNFT(nftOwner, nftData) - nftDatatoken = new Nft(web3, 8996, ERC721Template.abi as AbiItem[]) + nftDatatoken = new Nft(web3, 8996) }) + it('#getTokenURI', async () => { const tokenURI = await nftDatatoken.getTokenURI(nftAddress, 1) - assert(tokenURI === 'https://oceanprotocol.com/nft/') + assert(tokenURI === nftData.tokenURI) }) it('#createERC20 - should create a new ERC20 DT from NFT contract', async () => { @@ -66,11 +57,11 @@ describe('NFT', () => { nftOwner, user1, user2, - '0x0000000000000000000000000000000000000000', + ZERO_ADDRESS, '0', '10000', - nftName, - nftSymbol, + nftData.name, + nftData.symbol, 1 ) assert(erc20Address !== null) @@ -84,13 +75,14 @@ describe('NFT', () => { nftOwner, user1, user2, - '0x0000000000000000000000000000000000000000', + ZERO_ADDRESS, '0', '10000', - nftName, - nftSymbol, + nftData.name, + nftData.symbol, 1 ) + assert(false) } catch (e) { assert(e.message === 'Caller is not ERC20Deployer') } @@ -108,6 +100,7 @@ describe('NFT', () => { it('#addManager - should fail to add a new Manager, if NOT NFT Owner', async () => { try { await nftDatatoken.addManager(nftAddress, user1, user1) + assert(false) } catch (e) { assert(e.message === 'Caller is not NFT Owner') } @@ -124,6 +117,7 @@ describe('NFT', () => { it('#removeManager - should fail to remove a new Manager, if NOT NFT Owner', async () => { try { await nftDatatoken.removeManager(nftAddress, user1, nftOwner) + assert(false) } catch (e) { assert(e.message === 'Caller is not NFT Owner') } @@ -138,17 +132,10 @@ describe('NFT', () => { assert((await nftDatatoken.isErc20Deployer(nftAddress, user1)) === true) }) - it('#addManager - should fail to add a new Manager, if NOT NFT Owner', async () => { - try { - await nftDatatoken.addManager(nftAddress, user1, user1) - } catch (e) { - assert(e.message === 'Caller is not NFT Owner') - } - }) - it('#addERC20Deployer - should fail to add ERC20deployer if NOT Manager', async () => { try { await nftDatatoken.addErc20Deployer(nftAddress, user1, user1) + assert(false) } catch (e) { assert(e.message === 'Caller is not Manager') } @@ -167,16 +154,18 @@ describe('NFT', () => { assert((await nftDatatoken.isErc20Deployer(nftAddress, user1)) === true) try { await nftDatatoken.removeErc20Deployer(nftAddress, user1, user1) + assert(false) } catch (e) { assert(e.message === 'Caller is not Manager nor ERC20Deployer') } assert((await nftDatatoken.isErc20Deployer(nftAddress, user1)) === true) }) - it('#removeERC20Deployer - should fail to remove himself an ERC20Deployer', async () => { + it('#removeERC20Deployer - should fail to remove himself as an ERC20Deployer', async () => { assert((await nftDatatoken.isErc20Deployer(nftAddress, user1)) === true) try { await nftDatatoken.removeErc20Deployer(nftAddress, user1, user1) + assert(false) } catch (e) { assert(e.message === 'Caller is not Manager nor ERC20Deployer') } @@ -199,6 +188,7 @@ describe('NFT', () => { it('#addMetadataUpdate - should fail to add Metadata Updater if NOT Manager', async () => { try { await nftDatatoken.addMetadataUpdater(nftAddress, user1, user1) + assert(false) } catch (e) { assert(e.message === 'Caller is not Manager') } @@ -219,6 +209,7 @@ describe('NFT', () => { it('#removeMetadataUpdate - should fail to remove Metadata Updater if NOT Manager', async () => { try { await nftDatatoken.removeMetadataUpdater(nftAddress, user1, user1) + assert(false) } catch (e) { assert(e.message === 'Caller is not Manager nor Metadata Updater') } @@ -236,6 +227,7 @@ describe('NFT', () => { it('#addStoreUpdater - should fail to add Store Updater if NOT Manager', async () => { try { await nftDatatoken.addStoreUpdater(nftAddress, user1, user1) + assert(false) } catch (e) { assert(e.message === 'Caller is not Manager') } @@ -252,6 +244,7 @@ describe('NFT', () => { it('#removeStoreUpdater - should fail to remove Metadata Updater if NOT Manager', async () => { try { await nftDatatoken.removeStoreUpdater(nftAddress, user1, user1) + assert(false) } catch (e) { assert(e.message === `Caller is not Manager nor storeUpdater`) } @@ -263,6 +256,7 @@ describe('NFT', () => { try { await nftDatatoken.transferNft(nftAddress, user1, user1, 1) + assert(false) } catch (e) { assert(e.message === 'Caller is not NFT Owner') } @@ -277,14 +271,40 @@ describe('NFT', () => { await nftDatatoken.transferNft(nftAddress, nftOwner, user1, 1) assert((await nftDatatoken.getNftOwner(nftAddress)) === user1) - // console.log(await nftDatatoken.isErc20Deployer(nftAddress, user1)) - // assert((await nftDatatoken.isErc20Deployer(nftAddress, user1)) === false) + assert((await nftDatatoken.isErc20Deployer(nftAddress, nftOwner)) === false) + assert((await nftDatatoken.isErc20Deployer(nftAddress, user2)) === false) + }) + + // Safe transfer test + it('#safeTransferNft - should fail to transfer the NFT and clean all permissions, if NOT NFT Owner', async () => { + // return the nft to nftOwner to repeat transfer tests + await nftDatatoken.transferNft(nftAddress, user1, nftOwner, 1) + + assert((await nftDatatoken.getNftOwner(nftAddress)) !== user1) + + try { + await nftDatatoken.safeTransferNft(nftAddress, user1, user1, 1) + assert(false) + } catch (e) { + assert(e.message === 'Caller is not NFT Owner') + } + }) + + it('#safeTransferNft - should transfer the NFT and clean all permissions, set new owner as manager', async () => { + await nftDatatoken.addManager(nftAddress, nftOwner, user2) + await nftDatatoken.addErc20Deployer(nftAddress, user2, user1) + assert((await nftDatatoken.isErc20Deployer(nftAddress, user1)) === true) + + assert((await nftDatatoken.getNftOwner(nftAddress)) === nftOwner) + await nftDatatoken.safeTransferNft(nftAddress, nftOwner, user1, 1) + assert((await nftDatatoken.getNftOwner(nftAddress)) === user1) }) // Clear permisions it('#cleanPermissions - should fail to cleanPermissions if NOT NFTOwner', async () => { try { - await nftDatatoken.cleanPermissions(nftAddress, user1) + await nftDatatoken.cleanPermissions(nftAddress, user2) + assert(false) } catch (e) { assert(e.message === 'Caller is not NFT Owner') } @@ -304,38 +324,26 @@ describe('NFT', () => { it('#setMetaData - should succeed to update metadata if metadataUpdater', async () => { await nftDatatoken.addManager(nftAddress, user1, user1) await nftDatatoken.addMetadataUpdater(nftAddress, user1, user1) - const metaDataDecryptorUrl = 'http://myprovider:8030' - const metaDataDecryptorAddress = '0x123' - const metaDataState = 1 - const data = web3.utils.asciiToHex(user2) - const dataHash = '0x' + sha256(data).toString() - const flags = web3.utils.asciiToHex(user2) assert( (await nftDatatoken.getNftPermissions(nftAddress, user1)).updateMetadata === true ) await nftDatatoken.setMetadata( nftAddress, user1, - metaDataState, - metaDataDecryptorUrl, - metaDataDecryptorAddress, - flags, - data, - dataHash + 1, + 'http://myprovider:8030', + '0x123', + web3.utils.asciiToHex(user2), + web3.utils.asciiToHex(user2), + '0x' + sha256(web3.utils.asciiToHex(user2)).toString() ) const metadata = await nftDatatoken.getMetadata(nftAddress) - assert(metadata[0] === metaDataDecryptorUrl) - assert(metadata[1] === metaDataDecryptorAddress) - // assert((await nftDatatoken.getMetadata(nftAddress)).metaDataDecryptorAddress === metaDataDecryptorAddress) + assert(metadata[0] === 'http://myprovider:8030') + assert(metadata[1] === '0x123') }) + it('#setMetaData - should fail to update metadata if NOT metadataUpdater', async () => { - const metaDataDecryptorUrl = 'http://myprovider:8030' - const metaDataDecryptorAddress = '0x123' - const metaDataState = 1 - const data = web3.utils.asciiToHex(user2) - const dataHash = '0x' + sha256(data).toString() - const flags = web3.utils.asciiToHex(user2) assert( (await nftDatatoken.getNftPermissions(nftAddress, user3)).updateMetadata === false ) @@ -343,13 +351,14 @@ describe('NFT', () => { await nftDatatoken.setMetadata( nftAddress, user3, - metaDataState, - metaDataDecryptorUrl, - metaDataDecryptorAddress, - flags, - data, - dataHash + 1, + 'http://myprovider:8030', + '0x123', + web3.utils.asciiToHex(user2), + web3.utils.asciiToHex(user2), + '0x' + sha256(web3.utils.asciiToHex(user2)).toString() ) + assert(false) } catch (e) { assert(e.message === 'Caller is not Metadata updater') } @@ -357,6 +366,7 @@ describe('NFT', () => { (await nftDatatoken.getNftPermissions(nftAddress, user3)).updateMetadata === false ) }) + it('#setMetaDataState - should succeed to update MetadataState if metadataUpdater', async () => { await nftDatatoken.addManager(nftAddress, user1, user1) await nftDatatoken.addMetadataUpdater(nftAddress, user1, user1) @@ -381,6 +391,7 @@ describe('NFT', () => { ) try { await nftDatatoken.setMetadataState(nftAddress, user3, 1) + assert(false) } catch (e) { assert(e.message === 'Caller is not Metadata updater') } @@ -419,7 +430,7 @@ describe('NFT', () => { assert(tx.events.MetadataUpdated) const metadata = await nftDatatoken.getMetadata(nftAddress) - assert(metadata[0] === 'http://myprovider:8030') - assert(metadata[1] === '0x123') + assert(metadata[0] === metadataAndTokenURI.metaDataDecryptorUrl) + assert(metadata[1] === metadataAndTokenURI.metaDataDecryptorAddress) }) })