diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 887a8205..3fc4ff36 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -58,8 +58,6 @@ jobs: working-directory: ${{ github.workspace }}/barge run: | bash -x start_ocean.sh --no-aquarius --no-elasticsearch --no-provider --no-dashboard 2>&1 > start_ocean.log & - env: - CONTRACTS_VERSION: v1.0.0-alpha.31 - run: npm ci - name: Wait for contracts deployment working-directory: ${{ github.workspace }}/barge @@ -117,8 +115,6 @@ jobs: working-directory: ${{ github.workspace }}/barge run: | bash -x start_ocean.sh --with-provider2 --no-dashboard --with-c2d 2>&1 > start_ocean.log & - env: - CONTRACTS_VERSION: v1.0.0-alpha.31 - run: npm ci - run: npm run build:metadata diff --git a/CHANGELOG.md b/CHANGELOG.md index 240c064b..595058c0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,8 +4,46 @@ All notable changes to this project will be documented in this file. Dates are d Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). +#### [v1.0.0-next.42](https://github.com/oceanprotocol/ocean.js/compare/v1.0.0-next.41...v1.0.0-next.42) + +- bump contracts to alpha.32 [`#1464`](https://github.com/oceanprotocol/ocean.js/pull/1464) +- simple compute flow [`#1458`](https://github.com/oceanprotocol/ocean.js/pull/1458) +- add optional decimals parameter at joinswapExternAmountIn() and exitswapPoolAmountIn() [`#1461`](https://github.com/oceanprotocol/ocean.js/pull/1461) + +#### [v1.0.0-next.41](https://github.com/oceanprotocol/ocean.js/compare/v1.0.0-next.40...v1.0.0-next.41) + +> 6 May 2022 + +- Lock microbundle to v0.14.2 [`#1457`](https://github.com/oceanprotocol/ocean.js/pull/1457) +- Issue-#1345: Rewrite Provider test [`#1452`](https://github.com/oceanprotocol/ocean.js/pull/1452) +- Release 1.0.0-next.41 [`1d327bf`](https://github.com/oceanprotocol/ocean.js/commit/1d327bf1008917b2b04e03ae43840fa577d397d6) +- test getComputeEnvironments() [`997bbf5`](https://github.com/oceanprotocol/ocean.js/commit/997bbf57b4c05e6077abb3b7799be319815547b2) +- add assertion [`b40f52d`](https://github.com/oceanprotocol/ocean.js/commit/b40f52d6a68ab86b424839922b819cea08f869d2) + +#### [v1.0.0-next.40](https://github.com/oceanprotocol/ocean.js/compare/v1.0.0-next.39...v1.0.0-next.40) + +> 5 May 2022 + +- update default ESM export [`#1456`](https://github.com/oceanprotocol/ocean.js/pull/1456) +- Release 1.0.0-next.40 [`7782bf4`](https://github.com/oceanprotocol/ocean.js/commit/7782bf49b37cd88bfa000805cdff2bd6de716d5c) + +#### [v1.0.0-next.39](https://github.com/oceanprotocol/ocean.js/compare/v1.0.0-next.38...v1.0.0-next.39) + +> 5 May 2022 + +- Issue-#1409: Excessive contract calls [`#1424`](https://github.com/oceanprotocol/ocean.js/pull/1424) +- Issue-#1425: Use proper config in constructors [`#1430`](https://github.com/oceanprotocol/ocean.js/pull/1430) +- Bump release-it from 14.14.2 to 15.0.0 [`#1449`](https://github.com/oceanprotocol/ocean.js/pull/1449) +- Bump mocha from 9.2.2 to 10.0.0 [`#1450`](https://github.com/oceanprotocol/ocean.js/pull/1450) +- Bump @types/node from 17.0.30 to 17.0.31 [`#1451`](https://github.com/oceanprotocol/ocean.js/pull/1451) +- use getConfig(network) function to get proper configuration [`b259b16`](https://github.com/oceanprotocol/ocean.js/commit/b259b16d452b90ea05dfefcbcb3a52fe8b009d28) +- change param order [`2d744c3`](https://github.com/oceanprotocol/ocean.js/commit/2d744c3dd28566f1b2465085ec9b886e7943376f) +- Release 1.0.0-next.39 [`af5137c`](https://github.com/oceanprotocol/ocean.js/commit/af5137c3702ad03815ab6cb02265ccef45e7841d) + #### [v1.0.0-next.38](https://github.com/oceanprotocol/ocean.js/compare/v1.0.0-next.37...v1.0.0-next.38) +> 29 April 2022 + - bump to contracts alpha 31 [`#1448`](https://github.com/oceanprotocol/ocean.js/pull/1448) - Bump @truffle/hdwallet-provider from 2.0.7 to 2.0.8 [`#1445`](https://github.com/oceanprotocol/ocean.js/pull/1445) - Bump typescript from 4.6.3 to 4.6.4 [`#1446`](https://github.com/oceanprotocol/ocean.js/pull/1446) @@ -15,6 +53,7 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - Bump microbundle from 0.14.2 to 0.15.0 [`#1442`](https://github.com/oceanprotocol/ocean.js/pull/1442) - Bump @types/mocha from 9.1.0 to 9.1.1 [`#1431`](https://github.com/oceanprotocol/ocean.js/pull/1431) - Bump @truffle/hdwallet-provider from 2.0.6 to 2.0.7 [`#1432`](https://github.com/oceanprotocol/ocean.js/pull/1432) +- Release 1.0.0-next.38 [`f9db9ce`](https://github.com/oceanprotocol/ocean.js/commit/f9db9cea310dc3004438e6a7373fed5f0334d01d) #### [v1.0.0-next.37](https://github.com/oceanprotocol/ocean.js/compare/v1.0.0-next.36...v1.0.0-next.37) diff --git a/package-lock.json b/package-lock.json index 92a4023a..06f6d044 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15 +1,15 @@ { "name": "@oceanprotocol/lib", - "version": "1.0.0-next.38", + "version": "1.0.0-next.42", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@oceanprotocol/lib", - "version": "1.0.0-next.38", + "version": "1.0.0-next.42", "license": "Apache-2.0", "dependencies": { - "@oceanprotocol/contracts": "^1.0.0-alpha.31", + "@oceanprotocol/contracts": "^1.0.0-alpha.32", "bignumber.js": "^9.0.2", "cross-fetch": "^3.1.5", "crypto-js": "^4.1.1", @@ -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.31", + "@types/node": "^17.0.32", "@types/node-fetch": "^3.0.3", "@typescript-eslint/eslint-plugin": "^4.33.0", "@typescript-eslint/parser": "^4.33.0", @@ -37,7 +37,7 @@ "eslint-config-prettier": "^8.5.0", "eslint-plugin-prettier": "^4.0.0", "fs": "0.0.1-security", - "microbundle": "^0.15.0", + "microbundle": "0.14.2", "mocha": "^10.0.0", "mock-local-storage": "^1.1.21", "nyc": "^15.1.0", @@ -2471,9 +2471,9 @@ } }, "node_modules/@oceanprotocol/contracts": { - "version": "1.0.0-alpha.31", - "resolved": "https://registry.npmjs.org/@oceanprotocol/contracts/-/contracts-1.0.0-alpha.31.tgz", - "integrity": "sha512-WqrhjO0Qu8Bxdr2dAkdUL1Q/rHEkTuhx8OT4J/uJltnlxykCo6F8raNQAlhdh+84hm2Bv1irXE+PdpizNLwntQ==" + "version": "1.0.0-alpha.32", + "resolved": "https://registry.npmjs.org/@oceanprotocol/contracts/-/contracts-1.0.0-alpha.32.tgz", + "integrity": "sha512-gCHw4ZVnNjSozzCVT/cQiDqLNP0Xvy4fe+g5PKy8rwMR/h2rRW65Txi6wkb4HfZiUPKCdHbzpUFOwYfJFbW0Jw==" }, "node_modules/@octokit/auth-token": { "version": "2.5.0", @@ -3021,9 +3021,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "17.0.31", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.31.tgz", - "integrity": "sha512-AR0x5HbXGqkEx9CadRH3EBYx/VkiUgZIhP4wvPn/+5KIsgpNoyFaRlVe0Zlx9gRtg8fA06a9tskE2MSN7TcG4Q==" + "version": "17.0.32", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.32.tgz", + "integrity": "sha512-eAIcfAvhf/BkHcf4pkLJ7ECpBAhh9kcxRBpip9cTiO+hf+aJrsxYxBeS6OXvOd9WqNAJmavXVpZvY1rBjNsXmw==" }, "node_modules/@types/node-fetch": { "version": "3.0.3", @@ -11335,9 +11335,9 @@ } }, "node_modules/microbundle": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/microbundle/-/microbundle-0.15.0.tgz", - "integrity": "sha512-EkFst5ntLXoQGewkvga/Kd72RcN7IuJRl5ivLihJSbvLfJQo8LDS0n9X0q81vegiC59vhtKIM6qjrl1fOAtuGw==", + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/microbundle/-/microbundle-0.14.2.tgz", + "integrity": "sha512-jODALfU3w7jnJAqw7Tou9uU8e8zH0GRVWzOd/V7eAvD1fsfb9pyMbmzhFZqnX6SCb54eP1EF5oRyNlSxBAxoag==", "dev": true, "dependencies": { "@babel/core": "^7.12.10", @@ -11376,7 +11376,6 @@ "rollup-plugin-postcss": "^4.0.0", "rollup-plugin-terser": "^7.0.2", "rollup-plugin-typescript2": "^0.29.0", - "rollup-plugin-visualizer": "^5.6.0", "sade": "^1.7.4", "terser": "^5.7.0", "tiny-glob": "^0.2.8", @@ -15132,63 +15131,6 @@ "integrity": "sha512-SgIkNheinmEBgx1IUNirK0TUD4X9yjjBRTqqjggWCU3pUEqIk3/Uwl3yRixYKT6WjQuGiwDv4NomL3wqRCj+CQ==", "dev": true }, - "node_modules/rollup-plugin-visualizer": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/rollup-plugin-visualizer/-/rollup-plugin-visualizer-5.6.0.tgz", - "integrity": "sha512-CKcc8GTUZjC+LsMytU8ocRr/cGZIfMR7+mdy4YnlyetlmIl/dM8BMnOEpD4JPIGt+ZVW7Db9ZtSsbgyeBH3uTA==", - "dev": true, - "dependencies": { - "nanoid": "^3.1.32", - "open": "^8.4.0", - "source-map": "^0.7.3", - "yargs": "^17.3.1" - }, - "bin": { - "rollup-plugin-visualizer": "dist/bin/cli.js" - }, - "engines": { - "node": ">=12" - }, - "peerDependencies": { - "rollup": "^2.0.0" - } - }, - "node_modules/rollup-plugin-visualizer/node_modules/source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/rollup-plugin-visualizer/node_modules/yargs": { - "version": "17.4.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.4.1.tgz", - "integrity": "sha512-WSZD9jgobAg3ZKuCQZSa3g9QOJeCCqLoLAykiWgmXnDo9EPnn4RPf5qVTtzgOx66o6/oqhcA5tHtJXpG8pMt3g==", - "dev": true, - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/rollup-plugin-visualizer/node_modules/yargs-parser": { - "version": "21.0.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.1.tgz", - "integrity": "sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg==", - "dev": true, - "engines": { - "node": ">=12" - } - }, "node_modules/rollup-pluginutils": { "version": "2.8.2", "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", @@ -19668,9 +19610,9 @@ } }, "@oceanprotocol/contracts": { - "version": "1.0.0-alpha.31", - "resolved": "https://registry.npmjs.org/@oceanprotocol/contracts/-/contracts-1.0.0-alpha.31.tgz", - "integrity": "sha512-WqrhjO0Qu8Bxdr2dAkdUL1Q/rHEkTuhx8OT4J/uJltnlxykCo6F8raNQAlhdh+84hm2Bv1irXE+PdpizNLwntQ==" + "version": "1.0.0-alpha.32", + "resolved": "https://registry.npmjs.org/@oceanprotocol/contracts/-/contracts-1.0.0-alpha.32.tgz", + "integrity": "sha512-gCHw4ZVnNjSozzCVT/cQiDqLNP0Xvy4fe+g5PKy8rwMR/h2rRW65Txi6wkb4HfZiUPKCdHbzpUFOwYfJFbW0Jw==" }, "@octokit/auth-token": { "version": "2.5.0", @@ -20137,9 +20079,9 @@ "dev": true }, "@types/node": { - "version": "17.0.31", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.31.tgz", - "integrity": "sha512-AR0x5HbXGqkEx9CadRH3EBYx/VkiUgZIhP4wvPn/+5KIsgpNoyFaRlVe0Zlx9gRtg8fA06a9tskE2MSN7TcG4Q==" + "version": "17.0.32", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.32.tgz", + "integrity": "sha512-eAIcfAvhf/BkHcf4pkLJ7ECpBAhh9kcxRBpip9cTiO+hf+aJrsxYxBeS6OXvOd9WqNAJmavXVpZvY1rBjNsXmw==" }, "@types/node-fetch": { "version": "3.0.3", @@ -26645,9 +26587,9 @@ "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" }, "microbundle": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/microbundle/-/microbundle-0.15.0.tgz", - "integrity": "sha512-EkFst5ntLXoQGewkvga/Kd72RcN7IuJRl5ivLihJSbvLfJQo8LDS0n9X0q81vegiC59vhtKIM6qjrl1fOAtuGw==", + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/microbundle/-/microbundle-0.14.2.tgz", + "integrity": "sha512-jODALfU3w7jnJAqw7Tou9uU8e8zH0GRVWzOd/V7eAvD1fsfb9pyMbmzhFZqnX6SCb54eP1EF5oRyNlSxBAxoag==", "dev": true, "requires": { "@babel/core": "^7.12.10", @@ -26686,7 +26628,6 @@ "rollup-plugin-postcss": "^4.0.0", "rollup-plugin-terser": "^7.0.2", "rollup-plugin-typescript2": "^0.29.0", - "rollup-plugin-visualizer": "^5.6.0", "sade": "^1.7.4", "terser": "^5.7.0", "tiny-glob": "^0.2.8", @@ -29393,47 +29334,6 @@ } } }, - "rollup-plugin-visualizer": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/rollup-plugin-visualizer/-/rollup-plugin-visualizer-5.6.0.tgz", - "integrity": "sha512-CKcc8GTUZjC+LsMytU8ocRr/cGZIfMR7+mdy4YnlyetlmIl/dM8BMnOEpD4JPIGt+ZVW7Db9ZtSsbgyeBH3uTA==", - "dev": true, - "requires": { - "nanoid": "^3.1.32", - "open": "^8.4.0", - "source-map": "^0.7.3", - "yargs": "^17.3.1" - }, - "dependencies": { - "source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true - }, - "yargs": { - "version": "17.4.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.4.1.tgz", - "integrity": "sha512-WSZD9jgobAg3ZKuCQZSa3g9QOJeCCqLoLAykiWgmXnDo9EPnn4RPf5qVTtzgOx66o6/oqhcA5tHtJXpG8pMt3g==", - "dev": true, - "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.0.0" - } - }, - "yargs-parser": { - "version": "21.0.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.1.tgz", - "integrity": "sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg==", - "dev": true - } - } - }, "rollup-pluginutils": { "version": "2.8.2", "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", diff --git a/package.json b/package.json index ca9ad7df..a4725d46 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@oceanprotocol/lib", "source": "./src/index.ts", - "version": "1.0.0-next.38", + "version": "1.0.0-next.42", "description": "JavaScript client library for Ocean Protocol", "main": "./dist/lib.js", "umd:main": "dist/lib.umd.js", @@ -58,7 +58,7 @@ "web3": "^1.7.3" }, "dependencies": { - "@oceanprotocol/contracts": "^1.0.0-alpha.31", + "@oceanprotocol/contracts": "^1.0.0-alpha.32", "bignumber.js": "^9.0.2", "cross-fetch": "^3.1.5", "crypto-js": "^4.1.1", @@ -73,7 +73,7 @@ "@types/chai-spies": "^1.0.3", "@types/crypto-js": "^4.1.1", "@types/mocha": "^9.1.1", - "@types/node": "^17.0.31", + "@types/node": "^17.0.32", "@types/node-fetch": "^3.0.3", "@typescript-eslint/eslint-plugin": "^4.33.0", "@typescript-eslint/parser": "^4.33.0", @@ -86,7 +86,7 @@ "eslint-config-prettier": "^8.5.0", "eslint-plugin-prettier": "^4.0.0", "fs": "0.0.1-security", - "microbundle": "^0.15.0", + "microbundle": "0.14.2", "mocha": "^10.0.0", "mock-local-storage": "^1.1.21", "nyc": "^15.1.0", diff --git a/src/@types/Provider.ts b/src/@types/Provider.ts index d7ae662e..a8be432c 100644 --- a/src/@types/Provider.ts +++ b/src/@types/Provider.ts @@ -15,3 +15,14 @@ export interface ProviderInitialize { computeAddress: string providerFee: ProviderFees } + +export interface ProviderComputeInitialize { + datatoken?: string + validOrder?: string + providerFee?: ProviderFees +} + +export interface ProviderComputeInitializeResults { + algorithm?: ProviderComputeInitialize + datasets?: ProviderComputeInitialize[] +} diff --git a/src/pools/balancer/Pool.ts b/src/pools/balancer/Pool.ts index ca43bb0b..915131d6 100644 --- a/src/pools/balancer/Pool.ts +++ b/src/pools/balancer/Pool.ts @@ -1153,13 +1153,15 @@ export class Pool { * @param {String} poolAddress * @param {String} tokenAmountIn exact number of base tokens to spend * @param {String} minPoolAmountOut minimum of pool shares expectex + * @param {number} tokenInDecimals optional number of decimals of the token * @return {TransactionReceipt} */ async joinswapExternAmountIn( account: string, poolAddress: string, tokenAmountIn: string, - minPoolAmountOut: string + minPoolAmountOut: string, + tokenInDecimals?: number ): Promise { const pool = setContractDefaults( new this.web3.eth.Contract(this.poolAbi, poolAddress), @@ -1172,7 +1174,11 @@ export class Pool { throw new Error(`tokenAmountOut is greater than ${maxSwap.toString()}`) } - const amountInFormatted = await this.amountToUnits(tokenIn, tokenAmountIn) + const amountInFormatted = await this.amountToUnits( + tokenIn, + tokenAmountIn, + tokenInDecimals + ) const estGas = await this.estJoinswapExternAmountIn( account, poolAddress, @@ -1241,13 +1247,15 @@ export class Pool { * @param {String} poolAddress * @param {String} poolAmountIn exact number of pool shares to spend * @param {String} minTokenAmountOut minimum amount of basetokens expected + * @param {number} poolDecimals optional number of decimals of the poool * @return {TransactionReceipt} */ async exitswapPoolAmountIn( account: string, poolAddress: string, poolAmountIn: string, - minTokenAmountOut: string + minTokenAmountOut: string, + poolDecimals?: number ): Promise { const pool = setContractDefaults( new this.web3.eth.Contract(this.poolAbi, poolAddress), @@ -1269,7 +1277,8 @@ export class Pool { const minTokenOutFormatted = await this.amountToUnits( await this.getBaseToken(poolAddress), - minTokenAmountOut + minTokenAmountOut, + poolDecimals ) const estGas = await this.estExitswapPoolAmountIn( account, diff --git a/src/provider/Provider.ts b/src/provider/Provider.ts index f2116541..2bd87733 100644 --- a/src/provider/Provider.ts +++ b/src/provider/Provider.ts @@ -7,7 +7,8 @@ import { ComputeAlgorithm, ComputeAsset, ComputeEnvironment, - ProviderInitialize + ProviderInitialize, + ProviderComputeInitializeResults } from '../@types/' import { noZeroX } from '../utils/ConversionTypeHelper' import fetch from 'cross-fetch' @@ -327,6 +328,60 @@ export class Provider { } } + /** Initialize a compute request. + * @param {ComputeAsset} assets + * @param {ComputeAlgorithmber} algorithm + * @param {string} computeEnv + * @param {number} validUntil + * @param {string} providerUri Identifier of the asset to be registered in ocean + * @param {string} accountId + * @param {AbortSignal} signal abort signal + * @return {Promise} ProviderComputeInitialize data + */ + public async initializeCompute( + assets: ComputeAsset[], + algorithm: ComputeAlgorithm, + computeEnv: string, + validUntil: number, + providerUri: string, + accountId: string, + signal?: AbortSignal + ): Promise { + const providerEndpoints = await this.getEndpoints(providerUri) + const serviceEndpoints = await this.getServiceEndpoints( + providerUri, + providerEndpoints + ) + const providerData = { + datasets: assets, + algorithm: algorithm, + compute: { + env: computeEnv, + validUntil: validUntil + }, + consumerAddress: accountId + } + const initializeUrl = this.getEndpointURL(serviceEndpoints, 'initializeCompute') + ? this.getEndpointURL(serviceEndpoints, 'initializeCompute').urlPath + : null + if (!initializeUrl) return null + try { + const response = await fetch(initializeUrl, { + method: 'POST', + body: JSON.stringify(providerData), + headers: { + 'Content-Type': 'application/json' + }, + signal: signal + }) + const results = await response.json() + return results + } catch (e) { + LoggerInstance.error(e) + throw new Error('ComputeJob cannot be initialized') + } + } + /** Gets fully signed URL for download * @param {string} did * @param {string} accountId diff --git a/test/integration/ComputeFlow.test.ts b/test/integration/ComputeFlow.test.ts index 3a231035..aa494b08 100644 --- a/test/integration/ComputeFlow.test.ts +++ b/test/integration/ComputeFlow.test.ts @@ -8,11 +8,39 @@ import { NftFactory, NftCreateData, Datatoken, - getHash, Nft, - sleep + sleep, + ZERO_ADDRESS } from '../../src' -import { ProviderFees, Erc20CreateParams, ComputeJob, Asset } from '../../src/@types' +import { + Erc20CreateParams, + ComputeJob, + ComputeAsset, + ComputeAlgorithm, + ProviderComputeInitialize, + ConsumeMarketFee +} from '../../src/@types' + +let config: Config + +let aquarius: Aquarius +let datatoken: Datatoken +let providerUrl: string +let consumerAccount: string +let publisherAccount: string +let computeJobId: string +let providerInitializeComputeResults +let computeEnvs +let addresses: any +let ddoWith1mTimeoutId +let ddoWithNoTimeoutId +let algoDdoWith1mTimeoutId +let algoDdoWithNoTimeoutId + +let resolvedDdoWith1mTimeout +let resolvedDdoWithNoTimeout +let resolvedAlgoDdoWith1mTimeout +let resolvedAlgoDdoWithNoTimeout const assetUrl = [ { @@ -21,7 +49,7 @@ const assetUrl = [ method: 'GET' } ] -const ddo = { +const ddoWithNoTimeout = { '@context': ['https://w3id.org/did/v1'], id: 'did:op:efba17455c127a885ec7830d687a8f6e64f5ba559f8506f8723c1f10f05c049c', version: '4.0.0', @@ -52,13 +80,44 @@ const ddo = { publisherTrustedAlgorithmPublishers: [], publisherTrustedAlgorithms: [], allowRawAlgorithm: true, - allowNetworkAccess: true, - namespace: 'ocean-compute', - cpus: 2, - gpus: 4, - gpuType: 'NVIDIA Tesla V100 GPU', - memory: '128M', - volumeSize: '2G' + allowNetworkAccess: true + } + } + ] +} + +const ddoWith1mTimeout = { + '@context': ['https://w3id.org/did/v1'], + id: 'did:op:efba17455c127a885ec7830d687a8f6e64f5ba559f8506f8723c1f10f05c049c', + version: '4.0.0', + chainId: 4, + nftAddress: '0x0', + metadata: { + created: '2021-12-20T14:35:20Z', + updated: '2021-12-20T14:35:20Z', + type: 'dataset', + name: 'dfgdfgdg', + description: 'd dfgd fgd dfg dfgdfgd dfgdf', + tags: [''], + author: 'dd', + license: 'https://market.oceanprotocol.com/terms', + additionalInformation: { + termsAndConditions: true + } + }, + services: [ + { + id: 'notAnId', + type: 'compute', + files: '', + datatokenAddress: '0xa15024b732A8f2146423D14209eFd074e61964F3', + serviceEndpoint: 'https://providerv4.rinkeby.oceanprotocol.com', + timeout: 60, + compute: { + publisherTrustedAlgorithmPublishers: [], + publisherTrustedAlgorithms: [], + allowRawAlgorithm: true, + allowNetworkAccess: true } } ] @@ -70,7 +129,7 @@ const algoAssetUrl = [ method: 'GET' } ] -const algoDdo = { +const algoDdoWithNoTimeout = { '@context': ['https://w3id.org/did/v1'], id: 'did:op:efba17455c127a885ec7830d687a8f6e64f5ba559f8506f8723c1f10f05c049c', version: '4.0.0', @@ -110,144 +169,246 @@ const algoDdo = { } ] } -let providerUrl: string -let consumerAccount: string -let computeJobId: string -let resolvedDDOAsset: Asset + +const algoDdoWith1mTimeout = { + '@context': ['https://w3id.org/did/v1'], + id: 'did:op:efba17455c127a885ec7830d687a8f6e64f5ba559f8506f8723c1f10f05c049c', + version: '4.0.0', + chainId: 4, + nftAddress: '0x0', + metadata: { + created: '2021-12-20T14:35:20Z', + updated: '2021-12-20T14:35:20Z', + type: 'algorithm', + name: 'dfgdfgdg', + description: 'd dfgd fgd dfg dfgdfgd dfgdf', + tags: [''], + author: 'dd', + license: 'https://market.oceanprotocol.com/terms', + additionalInformation: { + termsAndConditions: true + }, + algorithm: { + language: 'Node.js', + version: '1.0.0', + container: { + entrypoint: 'node $ALGO', + image: 'ubuntu', + tag: 'latest', + checksum: '44e10daa6637893f4276bb8d7301eb35306ece50f61ca34dcab550' + } + } + }, + services: [ + { + id: 'notAnId', + type: 'access', + files: '', + datatokenAddress: '0xa15024b732A8f2146423D14209eFd074e61964F3', + serviceEndpoint: 'https://providerv4.rinkeby.oceanprotocol.com', + timeout: 60 + } + ] +} + +async function createAsset( + name: string, + symbol: string, + owner: string, + assetUrl: any, + ddo: any, + providerUrl: string +) { + const nft = new Nft(web3) + const Factory = new NftFactory(addresses.ERC721Factory, web3) + + const chain = await web3.eth.getChainId() + ddo.chainId = parseInt(chain.toString(10)) + const nftParamsAsset: NftCreateData = { + name: name, + symbol: symbol, + templateIndex: 1, + tokenURI: 'aaa', + transferable: true, + owner: owner + } + const erc20ParamsAsset: Erc20CreateParams = { + templateIndex: 1, + cap: '100000', + feeAmount: '0', + paymentCollector: ZERO_ADDRESS, + feeToken: ZERO_ADDRESS, + minter: owner, + mpFeeAddress: ZERO_ADDRESS + } + + const result = await Factory.createNftWithErc20(owner, nftParamsAsset, erc20ParamsAsset) + + const erc721AddressAsset = result.events.NFTCreated.returnValues[0] + const datatokenAddressAsset = result.events.TokenCreated.returnValues[0] + // create the files encrypted string + let providerResponse = await ProviderInstance.encrypt(assetUrl, providerUrl) + ddo.services[0].files = await providerResponse + ddo.services[0].datatokenAddress = datatokenAddressAsset + ddo.services[0].serviceEndpoint = providerUrl + // update ddo and set the right did + ddo.nftAddress = web3.utils.toChecksumAddress(erc721AddressAsset) + ddo.id = + 'did:op:' + + SHA256(web3.utils.toChecksumAddress(erc721AddressAsset) + chain.toString(10)) + providerResponse = await ProviderInstance.encrypt(ddo, providerUrl) + const encryptedResponse = await providerResponse + const validateResult = await aquarius.validate(ddo) + assert(validateResult.valid, 'Could not validate metadata') + await nft.setMetadata( + erc721AddressAsset, + owner, + 0, + providerUrl, + '', + '0x2', + encryptedResponse, + validateResult.hash + ) + return ddo.id +} + +async function handleOrder( + order: ProviderComputeInitialize, + datatokenAddress: string, + payerAccount: string, + consumerAccount: string, + serviceIndex: number, + consumeMarkerFee?: ConsumeMarketFee +) { + /* We do have 3 possible situations: + - have validOrder and no providerFees -> then order is valid, providerFees are valid, just use it in startCompute + - have validOrder and providerFees -> then order is valid but providerFees are not valid, we need to call reuseOrder and pay only providerFees + - no validOrder -> we need to call startOrder, to pay 1 DT & providerFees + */ + if (order.providerFee && order.providerFee.providerFeeAmount) { + await datatoken.approve( + order.providerFee.providerFeeToken, + datatokenAddress, + order.providerFee.providerFeeAmount, + payerAccount + ) + } + if (order.validOrder) { + if (!order.providerFee) return order.validOrder + const tx = await datatoken.reuseOrder( + datatokenAddress, + payerAccount, + order.validOrder, + order.providerFee + ) + return tx.transactionHash + } + const tx = await datatoken.startOrder( + datatokenAddress, + payerAccount, + consumerAccount, + serviceIndex, + order.providerFee, + consumeMarkerFee + ) + return tx.transactionHash +} describe('Simple compute tests', async () => { - let config: Config - let addresses: any - let aquarius: Aquarius - before(async () => { config = await getTestConfig(web3) addresses = getAddresses() aquarius = new Aquarius(config.metadataCacheUri) providerUrl = config.providerUri + datatoken = new Datatoken(web3) }) - it('should publish a dataset, algorithm and start a compute job', async () => { - const nft = new Nft(web3) - const datatoken = new Datatoken(web3) - const Factory = new NftFactory(addresses.ERC721Factory, web3) + it('should publish datasets and algorithms', async () => { const accounts = await web3.eth.getAccounts() - const publisherAccount = accounts[0] + publisherAccount = accounts[0] consumerAccount = accounts[1] - const chain = await web3.eth.getChainId() - const nftParamsAsset: NftCreateData = { - name: 'testNFT', - symbol: 'TST', - templateIndex: 1, - tokenURI: 'aaa', - transferable: true, - owner: publisherAccount - } - const erc20ParamsAsset: Erc20CreateParams = { - templateIndex: 1, - cap: '100000', - feeAmount: '0', - paymentCollector: '0x0000000000000000000000000000000000000000', - feeToken: '0x0000000000000000000000000000000000000000', - minter: publisherAccount, - mpFeeAddress: '0x0000000000000000000000000000000000000000' - } - - const result = await Factory.createNftWithErc20( + ddoWith1mTimeoutId = await createAsset( + 'D1Min', + 'D1M', publisherAccount, - nftParamsAsset, - erc20ParamsAsset + assetUrl, + ddoWith1mTimeout, + providerUrl + ) + ddoWithNoTimeoutId = await createAsset( + 'D1Min', + 'D1M', + publisherAccount, + assetUrl, + ddoWithNoTimeout, + providerUrl + ) + algoDdoWith1mTimeoutId = await createAsset( + 'A1Min', + 'A1M', + publisherAccount, + algoAssetUrl, + algoDdoWith1mTimeout, + providerUrl ) - const erc721AddressAsset = result.events.NFTCreated.returnValues[0] - const datatokenAddressAsset = result.events.TokenCreated.returnValues[0] - // create the files encrypted string - let providerResponse = await ProviderInstance.encrypt(assetUrl, providerUrl) - ddo.services[0].files = await providerResponse - ddo.services[0].datatokenAddress = datatokenAddressAsset - // update ddo and set the right did - ddo.nftAddress = erc721AddressAsset - ddo.id = - 'did:op:' + - SHA256(web3.utils.toChecksumAddress(erc721AddressAsset) + chain.toString(10)) - - providerResponse = await ProviderInstance.encrypt(ddo, providerUrl) - - let encryptedResponse = await providerResponse - let metadataHash = getHash(JSON.stringify(ddo)) - let res = await nft.setMetadata( - erc721AddressAsset, + algoDdoWithNoTimeoutId = await createAsset( + 'A1Min', + 'A1M', publisherAccount, - 0, - providerUrl, - '', - '0x2', - encryptedResponse, - '0x' + metadataHash + algoAssetUrl, + algoDdoWithNoTimeout, + providerUrl ) - // let's publish the algorithm as well - const nftParamsAlgo: NftCreateData = { - name: 'testNFT', - symbol: 'TST', - templateIndex: 1, - tokenURI: '', - transferable: true, - owner: publisherAccount - } - const erc20ParamsAlgo: Erc20CreateParams = { - templateIndex: 1, - cap: '100000', - feeAmount: '0', - paymentCollector: '0x0000000000000000000000000000000000000000', - feeToken: '0x0000000000000000000000000000000000000000', - minter: publisherAccount, - mpFeeAddress: '0x0000000000000000000000000000000000000000' - } - const resultAlgo = await Factory.createNftWithErc20( + }) + + it('should resolve published datasets and algorithms', async () => { + resolvedDdoWith1mTimeout = await aquarius.waitForAqua(ddoWith1mTimeoutId) + assert(resolvedDdoWith1mTimeout, 'Cannot fetch DDO from Aquarius') + resolvedDdoWithNoTimeout = await aquarius.waitForAqua(ddoWithNoTimeoutId) + assert(resolvedDdoWithNoTimeout, 'Cannot fetch DDO from Aquarius') + resolvedAlgoDdoWith1mTimeout = await aquarius.waitForAqua(algoDdoWith1mTimeoutId) + assert(resolvedAlgoDdoWith1mTimeout, 'Cannot fetch DDO from Aquarius') + resolvedAlgoDdoWithNoTimeout = await aquarius.waitForAqua(algoDdoWithNoTimeoutId) + assert(resolvedAlgoDdoWithNoTimeout, 'Cannot fetch DDO from Aquarius') + }) + + it('should send DT to consumer', async () => { + const datatoken = new Datatoken(web3) + await datatoken.mint( + resolvedDdoWith1mTimeout.services[0].datatokenAddress, publisherAccount, - nftParamsAlgo, - erc20ParamsAlgo + '10', + consumerAccount ) - const erc721AddressAlgo = resultAlgo.events.NFTCreated.returnValues[0] - const datatokenAddressAlgo = resultAlgo.events.TokenCreated.returnValues[0] - - // create the files encrypted string - providerResponse = await ProviderInstance.encrypt(algoAssetUrl, providerUrl) - algoDdo.services[0].files = await providerResponse - algoDdo.services[0].datatokenAddress = datatokenAddressAlgo - // update ddo and set the right did - algoDdo.nftAddress = erc721AddressAlgo - - algoDdo.id = - 'did:op:' + - SHA256(web3.utils.toChecksumAddress(erc721AddressAlgo) + chain.toString(10)) - - providerResponse = await ProviderInstance.encrypt(algoDdo, providerUrl) - encryptedResponse = await providerResponse - metadataHash = getHash(JSON.stringify(algoDdo)) - res = await nft.setMetadata( - erc721AddressAlgo, + await datatoken.mint( + resolvedDdoWithNoTimeout.services[0].datatokenAddress, publisherAccount, - 0, - providerUrl, - '', - '0x2', - encryptedResponse, - '0x' + metadataHash + '10', + consumerAccount ) + await datatoken.mint( + resolvedAlgoDdoWith1mTimeout.services[0].datatokenAddress, + publisherAccount, + '10', + consumerAccount + ) + await datatoken.mint( + resolvedAlgoDdoWithNoTimeout.services[0].datatokenAddress, + publisherAccount, + '10', + consumerAccount + ) + }) - // let's wait - resolvedDDOAsset = await aquarius.waitForAqua(ddo.id) - assert(resolvedDDOAsset, 'Cannot fetch DDO from Aquarius') - const resolvedDDOAlgo = await aquarius.waitForAqua(algoDdo.id) - assert(resolvedDDOAlgo, 'Cannot fetch DDO from Aquarius') - // mint 1 ERC20 and send it to the consumer - await datatoken.mint(datatokenAddressAsset, publisherAccount, '1', consumerAccount) - await datatoken.mint(datatokenAddressAlgo, publisherAccount, '1', consumerAccount) - + it('should fetch compute environments from provider', async () => { // get compute environments - const computeEnvs = await ProviderInstance.getComputeEnvironments(providerUrl) + computeEnvs = await ProviderInstance.getComputeEnvironments(providerUrl) assert(computeEnvs, 'No Compute environments found') + }) + + it('should start a computeJob', async () => { // we choose the first env const computeEnv = computeEnvs[0].id const computeConsumerAddress = computeEnvs[0].consumerAddress @@ -255,89 +416,53 @@ describe('Simple compute tests', async () => { const mytime = new Date() mytime.setMinutes(mytime.getMinutes() + 19) const computeValidUntil = Math.floor(mytime.getTime() / 1000) - // initialize provider orders for algo - const initializeDataAlgo = await ProviderInstance.initialize( - resolvedDDOAlgo.id, - resolvedDDOAlgo.services[0].id, - 0, - consumerAccount, - providerUrl, - null, - null, - computeEnv, - computeValidUntil - ) - const providerAlgoFees: ProviderFees = { - providerFeeAddress: initializeDataAlgo.providerFee.providerFeeAddress, - providerFeeToken: initializeDataAlgo.providerFee.providerFeeToken, - providerFeeAmount: initializeDataAlgo.providerFee.providerFeeAmount, - v: initializeDataAlgo.providerFee.v, - r: initializeDataAlgo.providerFee.r, - s: initializeDataAlgo.providerFee.s, - providerData: initializeDataAlgo.providerFee.providerData, - validUntil: initializeDataAlgo.providerFee.validUntil + const assets: ComputeAsset[] = [ + { + documentId: resolvedDdoWith1mTimeout.id, + serviceId: resolvedDdoWith1mTimeout.services[0].id + } + ] + const dtAddressArray = [resolvedDdoWith1mTimeout.services[0].datatokenAddress] + const algo: ComputeAlgorithm = { + documentId: resolvedAlgoDdoWith1mTimeout.id, + serviceId: resolvedAlgoDdoWith1mTimeout.services[0].id } - // make the payment - const txidAlgo = await datatoken.startOrder( - datatokenAddressAlgo, - consumerAccount, - computeConsumerAddress, // this is important because the c2d is the consumer, and user is the payer. Otherwise, c2d will have no access to the asset - 0, - providerAlgoFees - ) - assert(txidAlgo, 'Failed to order algo') - - const providerValidUntil = new Date() - providerValidUntil.setHours(providerValidUntil.getHours() + 1) - - // initialize provider orders for asset - const initializeData = await ProviderInstance.initialize( - resolvedDDOAsset.id, - resolvedDDOAsset.services[0].id, - 0, - consumerAccount, - providerUrl, - null, - null, + providerInitializeComputeResults = await ProviderInstance.initializeCompute( + assets, + algo, computeEnv, - computeValidUntil + computeValidUntil, + providerUrl, + consumerAccount ) - const providerDatasetFees: ProviderFees = { - providerFeeAddress: initializeData.providerFee.providerFeeAddress, - providerFeeToken: initializeData.providerFee.providerFeeToken, - providerFeeAmount: initializeData.providerFee.providerFeeAmount, - v: initializeData.providerFee.v, - r: initializeData.providerFee.r, - s: initializeData.providerFee.s, - providerData: initializeData.providerFee.providerData, - validUntil: initializeData.providerFee.validUntil - } - // make the payment - const txidAsset = await datatoken.startOrder( - datatokenAddressAsset, + assert( + !('error' in providerInitializeComputeResults.algorithm), + 'Cannot order algorithm' + ) + algo.transferTxId = await handleOrder( + providerInitializeComputeResults.algorithm, + resolvedAlgoDdoWith1mTimeout.services[0].datatokenAddress, consumerAccount, - computeConsumerAddress, // this is important because the c2d is the consumer, and user is the payer. Otherwise, c2d will have no access to the asset - 0, - providerDatasetFees + computeConsumerAddress, + 0 ) - assert(txidAsset, 'Failed to order algo') - // start the compute job + for (let i = 0; i < providerInitializeComputeResults.datasets.length; i++) { + assets[i].transferTxId = await handleOrder( + providerInitializeComputeResults.datasets[i], + dtAddressArray[i], + consumerAccount, + computeConsumerAddress, + 0 + ) + } const computeJobs = await ProviderInstance.computeStart( providerUrl, web3, consumerAccount, computeEnv, - { - documentId: resolvedDDOAsset.id, - serviceId: resolvedDDOAsset.services[0].id, - transferTxId: txidAsset.transactionHash - }, - { - documentId: resolvedDDOAlgo.id, - serviceId: resolvedDDOAlgo.services[0].id, - transferTxId: txidAlgo.transactionHash - } + assets[0], + algo ) assert(computeJobs, 'Cannot start compute job') computeJobId = computeJobs[0].jobId @@ -348,7 +473,7 @@ describe('Simple compute tests', async () => { providerUrl, consumerAccount, computeJobId, - resolvedDDOAsset.id + resolvedDdoWith1mTimeout.id )) as ComputeJob assert(jobStatus, 'Cannot retrieve compute status!') }) diff --git a/test/integration/Provider.test.ts b/test/integration/Provider.test.ts index b35ffb97..94c083ee 100644 --- a/test/integration/Provider.test.ts +++ b/test/integration/Provider.test.ts @@ -32,4 +32,9 @@ describe('Provider tests', async () => { ) assert(fileinfo[0].valid === true, 'Sent file is not valid') }) + + it('Alice tests compute environments', async () => { + const computeEnvs = await providerInstance.getComputeEnvironments(config.providerUri) + assert(computeEnvs, 'No Compute environments found') + }) })