From 718247aacd052c79c7d0ec3733bb24e884bf9b9e Mon Sep 17 00:00:00 2001 From: Pierre Jeanjacquot <26487010+PierreJeanjacquot@users.noreply.github.com> Date: Fri, 28 Jun 2024 11:24:43 +0200 Subject: [PATCH 01/20] more permissive url validation for `iexec_input_files` --- CHANGELOG.md | 4 ++++ src/common/utils/validator.js | 12 ++++-------- test/lib/unit/validator.test.js | 16 +++++++++------- 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fa929546..b6829dc6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ All notable changes to this project will be documented in this file. +## NEXT + +- more permissive url validation for `iexec_input_files` + ## [8.9.1] 2024-06-19 ### Changed diff --git a/src/common/utils/validator.js b/src/common/utils/validator.js index 701972d5..cd8a860c 100644 --- a/src/common/utils/validator.js +++ b/src/common/utils/validator.js @@ -69,6 +69,9 @@ export const uint256Schema = () => export const booleanSchema = () => boolean(); +export const basicUrlSchema = () => + string().matches(/^http[s]?:\/\//, '${path} "${value}" is not a valid URL'); + const amountErrorMessage = ({ originalValue }) => `${ Array.isArray(originalValue) ? originalValue.join(' ') : originalValue @@ -263,11 +266,7 @@ export const paramsInputFilesArraySchema = () => } return value; }) - .of( - string() - .url('${path} "${value}" is not a valid URL') - .required('${path} "${value}" is not a valid URL'), - ); + .of(basicUrlSchema().required('${path} "${value}" is not a valid URL')); export const paramsEncryptResultSchema = () => boolean(); @@ -831,9 +830,6 @@ export const textRecordValueSchema = () => string().default('').strict(true); export const workerpoolApiUrlSchema = () => string().url().default(''); -export const basicUrlSchema = () => - string().matches(/^http[s]?:\/\//, '${path} is not a valid url'); - export const smsUrlOrMapSchema = () => lazy((stringOrMap) => { if (typeof stringOrMap === 'object' && stringOrMap !== null) { diff --git a/test/lib/unit/validator.test.js b/test/lib/unit/validator.test.js index d0913a11..9f22b053 100644 --- a/test/lib/unit/validator.test.js +++ b/test/lib/unit/validator.test.js @@ -484,11 +484,13 @@ describe('[paramsInputFilesArraySchema]', () => { await expect( paramsInputFilesArraySchema().validate([ 'https://iex.ec/wp-content/uploads/pdf/iExec-WPv3.0-English.pdf', - 'https://iex.ec/wp-content/uploads/pdf/iExec-WPv3.0-English.pdf', + 'http://iex.ec/wp-content/uploads/pdf/iExec-WPv3.0-English.pdf', + 'http://docker-service:8080/uploads/pdf/iExec-WPv3.0-English.pdf', ]), ).resolves.toEqual([ 'https://iex.ec/wp-content/uploads/pdf/iExec-WPv3.0-English.pdf', - 'https://iex.ec/wp-content/uploads/pdf/iExec-WPv3.0-English.pdf', + 'http://iex.ec/wp-content/uploads/pdf/iExec-WPv3.0-English.pdf', + 'http://docker-service:8080/uploads/pdf/iExec-WPv3.0-English.pdf', ]); }); test('string comma separated list of URL', async () => { @@ -728,14 +730,14 @@ describe('[objParamsSchema]', () => { { iexec_input_files: [ 'https://iex.ec/wp-content/uploads/pdf/iExec-WPv3.0-English.pdf', - 'https://iexec/wp-content/uploads/pdf/iExec-WPv3.0-English.pdf', + 'iex.ec/wp-content/uploads/pdf/iExec-WPv3.0-English.pdf', ], }, { context: { resultProxyURL: 'https://result-proxy.iex.ec' } }, ), ).rejects.toThrow( new ValidationError( - 'iexec_input_files[1] "https://iexec/wp-content/uploads/pdf/iExec-WPv3.0-English.pdf" is not a valid URL', + 'iexec_input_files[1] "iex.ec/wp-content/uploads/pdf/iExec-WPv3.0-English.pdf" is not a valid URL', ), ); }); @@ -1483,7 +1485,7 @@ describe('[smsUrlOrMapSchema]', () => { }); test('throw with empty string', async () => { await expect(smsUrlOrMapSchema().validate('')).rejects.toThrow( - 'this is not a valid url', + 'this "" is not a valid URL', ); }); test('throw with null', async () => { @@ -1493,7 +1495,7 @@ describe('[smsUrlOrMapSchema]', () => { }); test('throw with invalid url', async () => { await expect(smsUrlOrMapSchema().validate('foo')).rejects.toThrow( - 'this is not a valid url', + 'this "foo" is not a valid URL', ); }); test('throw with unknown TEE framework key', async () => { @@ -1504,7 +1506,7 @@ describe('[smsUrlOrMapSchema]', () => { test('throw with invalid url on a TEE framework key', async () => { await expect( smsUrlOrMapSchema().validate({ scone: 'foo' }), - ).rejects.toThrow('scone is not a valid url'); + ).rejects.toThrow('scone "foo" is not a valid URL'); }); }); From c0a10347dfb3213f54213f5646c2afc6d7fcaf95 Mon Sep 17 00:00:00 2001 From: Pierre Jeanjacquot <26487010+PierreJeanjacquot@users.noreply.github.com> Date: Wed, 17 Jul 2024 12:05:01 +0200 Subject: [PATCH 02/20] update ethers --- package-lock.json | 144 ++++++++++++++-------------------------------- package.json | 2 +- 2 files changed, 44 insertions(+), 102 deletions(-) diff --git a/package-lock.json b/package-lock.json index 64dff490..2b238983 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,7 +17,7 @@ "buffer": "^6.0.3", "commander": "^11.1.0", "debug": "^4.3.4", - "ethers": "^6.8.0", + "ethers": "^6.13.1", "fs-extra": "^11.1.1", "image-size": "^1.0.2", "inquirer": "^9.2.11", @@ -62,9 +62,9 @@ } }, "node_modules/@adraffy/ens-normalize": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.0.tgz", - "integrity": "sha512-nA9XHtlAkYfJxY7bce8DcN7eKxWWCWkU+1GR9d+U6MbNpfwQp8TI7vqOsBsMcHoT4mBu2kypKoSKnghEzOOq5Q==" + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz", + "integrity": "sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==" }, "node_modules/@ampproject/remapping": { "version": "2.2.1", @@ -2238,19 +2238,6 @@ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true }, - "node_modules/bufferutil": { - "version": "4.0.6", - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "node-gyp-build": "^4.3.0" - }, - "engines": { - "node": ">=6.14.2" - } - }, "node_modules/call-bind": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", @@ -3124,9 +3111,9 @@ } }, "node_modules/ethers": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.8.0.tgz", - "integrity": "sha512-zrFbmQRlraM+cU5mE4CZTLBurZTs2gdp2ld0nG/f3ecBK+x6lZ69KSxBqZ4NjclxwfTxl5LeNufcBbMsTdY53Q==", + "version": "6.13.1", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.13.1.tgz", + "integrity": "sha512-hdJ2HOxg/xx97Lm9HdCWk949BfYqYWpyw4//78SiwOLgASyfrNszfMUNB2joKjvGUdwhHfaiMMFFwacVVoLR9A==", "funding": [ { "type": "individual", @@ -3138,13 +3125,13 @@ } ], "dependencies": { - "@adraffy/ens-normalize": "1.10.0", + "@adraffy/ens-normalize": "1.10.1", "@noble/curves": "1.2.0", "@noble/hashes": "1.3.2", "@types/node": "18.15.13", "aes-js": "4.0.0-beta.5", "tslib": "2.4.0", - "ws": "8.5.0" + "ws": "8.17.1" }, "engines": { "node": ">=14.0.0" @@ -3166,26 +3153,6 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" }, - "node_modules/ethers/node_modules/ws": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", - "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, "node_modules/execa": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", @@ -5351,17 +5318,6 @@ "node": ">= 6.13.0" } }, - "node_modules/node-gyp-build": { - "version": "4.4.0", - "license": "MIT", - "optional": true, - "peer": true, - "bin": { - "node-gyp-build": "bin.js", - "node-gyp-build-optional": "optional.js", - "node-gyp-build-test": "build-test.js" - } - }, "node_modules/node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", @@ -7102,19 +7058,6 @@ "punycode": "^2.1.0" } }, - "node_modules/utf-8-validate": { - "version": "5.0.9", - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "node-gyp-build": "^4.3.0" - }, - "engines": { - "node": ">=6.14.2" - } - }, "node_modules/util-deprecate": { "version": "1.0.2", "license": "MIT" @@ -7267,6 +7210,26 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, + "node_modules/ws": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", @@ -7349,9 +7312,9 @@ "dev": true }, "@adraffy/ens-normalize": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.0.tgz", - "integrity": "sha512-nA9XHtlAkYfJxY7bce8DcN7eKxWWCWkU+1GR9d+U6MbNpfwQp8TI7vqOsBsMcHoT4mBu2kypKoSKnghEzOOq5Q==" + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz", + "integrity": "sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==" }, "@ampproject/remapping": { "version": "2.2.1", @@ -9010,14 +8973,6 @@ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true }, - "bufferutil": { - "version": "4.0.6", - "optional": true, - "peer": true, - "requires": { - "node-gyp-build": "^4.3.0" - } - }, "call-bind": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", @@ -9626,17 +9581,17 @@ "dev": true }, "ethers": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.8.0.tgz", - "integrity": "sha512-zrFbmQRlraM+cU5mE4CZTLBurZTs2gdp2ld0nG/f3ecBK+x6lZ69KSxBqZ4NjclxwfTxl5LeNufcBbMsTdY53Q==", + "version": "6.13.1", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.13.1.tgz", + "integrity": "sha512-hdJ2HOxg/xx97Lm9HdCWk949BfYqYWpyw4//78SiwOLgASyfrNszfMUNB2joKjvGUdwhHfaiMMFFwacVVoLR9A==", "requires": { - "@adraffy/ens-normalize": "1.10.0", + "@adraffy/ens-normalize": "1.10.1", "@noble/curves": "1.2.0", "@noble/hashes": "1.3.2", "@types/node": "18.15.13", "aes-js": "4.0.0-beta.5", "tslib": "2.4.0", - "ws": "8.5.0" + "ws": "8.17.1" }, "dependencies": { "@noble/hashes": { @@ -9648,12 +9603,6 @@ "version": "2.4.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" - }, - "ws": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", - "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", - "requires": {} } } }, @@ -11132,11 +11081,6 @@ "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==" }, - "node-gyp-build": { - "version": "4.4.0", - "optional": true, - "peer": true - }, "node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", @@ -12323,14 +12267,6 @@ "punycode": "^2.1.0" } }, - "utf-8-validate": { - "version": "5.0.9", - "optional": true, - "peer": true, - "requires": { - "node-gyp-build": "^4.3.0" - } - }, "util-deprecate": { "version": "1.0.2" }, @@ -12443,6 +12379,12 @@ "signal-exit": "^3.0.7" } }, + "ws": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "requires": {} + }, "y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", diff --git a/package.json b/package.json index 4d2c22a0..7dec0de6 100644 --- a/package.json +++ b/package.json @@ -197,7 +197,7 @@ "buffer": "^6.0.3", "commander": "^11.1.0", "debug": "^4.3.4", - "ethers": "^6.8.0", + "ethers": "^6.13.1", "fs-extra": "^11.1.1", "image-size": "^1.0.2", "inquirer": "^9.2.11", From fa576087bd3198514537737de01589ce06758558 Mon Sep 17 00:00:00 2001 From: Pierre Jeanjacquot <26487010+PierreJeanjacquot@users.noreply.github.com> Date: Wed, 17 Jul 2024 13:56:57 +0200 Subject: [PATCH 03/20] add chainstack provider --- src/common/utils/providers.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/common/utils/providers.js b/src/common/utils/providers.js index 2a047c87..4d3135ce 100644 --- a/src/common/utils/providers.js +++ b/src/common/utils/providers.js @@ -36,6 +36,7 @@ export const getReadOnlyProvider = (host, options = {}) => { 'etherscan', 'infura', 'pocket', // currently commented in ethers + 'chainstack', 'quicknode', ]; const nonConfiguredProviders = apiProvidersList.filter( From 634f3cf403d2ef947da22d2f4f35ba4056e2ead7 Mon Sep 17 00:00:00 2001 From: Pierre Jeanjacquot <26487010+PierreJeanjacquot@users.noreply.github.com> Date: Thu, 18 Jul 2024 14:25:22 +0200 Subject: [PATCH 04/20] reduce polling interval --- src/cli/utils/chains.js | 26 ++++++++++++------- src/lib/IExecConfig.js | 1 + .../prepare-bellecour-fork-for-tests.js | 4 ++- test/test-utils.js | 5 +++- 4 files changed, 25 insertions(+), 11 deletions(-) diff --git a/src/cli/utils/chains.js b/src/cli/utils/chains.js index 5a71637b..0cf576c7 100644 --- a/src/cli/utils/chains.js +++ b/src/cli/utils/chains.js @@ -40,11 +40,15 @@ const createChainFromConf = ( const chain = { ...chainConf }; const provider = chainConf.host && chainConf.host.indexOf('http') === 0 - ? new JsonRpcProvider(chainConf.host, { - ensAddress: chainConf.ensRegistry, - chainId: parseInt(chainConf.id, 10), - name: chainName, - }) + ? new JsonRpcProvider( + chainConf.host, + { + ensAddress: chainConf.ensRegistry, + chainId: parseInt(chainConf.id, 10), + name: chainName, + }, + { pollingInterval: 1000 }, // override default polling interval (4000) for faster confirmation + ) : getReadOnlyProvider(chainConf.host, { providers: providerOptions }); chain.name = chainName; @@ -62,10 +66,14 @@ const createChainFromConf = ( chain.bridgedNetwork = { ...bridgeConf }; const bridgeProvider = bridgeConf.host && bridgeConf.host.indexOf('http') === 0 - ? new JsonRpcProvider(bridgeConf.host, { - ensAddress: bridgeConf.ensRegistry, - chainId: parseInt(bridgeConf.id, 10), - }) + ? new JsonRpcProvider( + bridgeConf.host, + { + ensAddress: bridgeConf.ensRegistry, + chainId: parseInt(bridgeConf.id, 10), + }, + { pollingInterval: 1000 }, // override default polling interval (4000) for faster confirmation) + ) : getReadOnlyProvider(bridgeConf.host, { providers: providerOptions, }); diff --git a/src/lib/IExecConfig.js b/src/lib/IExecConfig.js index 0aa0dcce..7a9a57bb 100644 --- a/src/lib/IExecConfig.js +++ b/src/lib/IExecConfig.js @@ -129,6 +129,7 @@ export default class IExecConfig { // eslint-disable-next-line no-underscore-dangle ethProvider.provider._getConnection().url, networkOverride, + { pollingInterval: 1000 }, // override default polling interval (4000) for faster confirmation ), ); } else { diff --git a/test/scripts/prepare-bellecour-fork-for-tests.js b/test/scripts/prepare-bellecour-fork-for-tests.js index c7094540..f1691eaf 100755 --- a/test/scripts/prepare-bellecour-fork-for-tests.js +++ b/test/scripts/prepare-bellecour-fork-for-tests.js @@ -14,7 +14,9 @@ const TARGET_FAUCET_WALLET = '0xdFa2585C16cAf9c853086F36d2A37e9b8d1eab87'; const rpcURL = DRONE ? 'http://bellecour-fork:8545' : 'http://localhost:8545'; -const provider = new JsonRpcProvider(rpcURL); +const provider = new JsonRpcProvider(rpcURL, undefined, { + pollingInterval: 100, // fast polling for tests +}); const setBalance = async (address, weiAmount) => { fetch(rpcURL, { diff --git a/test/test-utils.js b/test/test-utils.js index e61b7df6..fd17923f 100644 --- a/test/test-utils.js +++ b/test/test-utils.js @@ -128,7 +128,10 @@ export const getRandomAddress = () => getRandomWallet().address; export const getRandomBytes32 = () => hexlify(randomBytes(32)); export class InjectedProvider { constructor(rpcUrl, privateKey) { - this.signer = new Wallet(privateKey, new JsonRpcProvider(rpcUrl)); + this.signer = new Wallet( + privateKey, + new JsonRpcProvider(rpcUrl, undefined, { pollingInterval: 100 }), // fast polling for tests + ); } async request(args) { From 517101b61bc256cb2a4319ef7aa6f45d9b6f22e8 Mon Sep 17 00:00:00 2001 From: Pierre Jeanjacquot <26487010+PierreJeanjacquot@users.noreply.github.com> Date: Fri, 19 Jul 2024 11:26:26 +0200 Subject: [PATCH 05/20] add bellecour to ethers networks --- src/common/utils/config.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/common/utils/config.js b/src/common/utils/config.js index cd8c71a5..91ecdac4 100644 --- a/src/common/utils/config.js +++ b/src/common/utils/config.js @@ -1,3 +1,4 @@ +import { Network, EnsPlugin } from 'ethers'; import { TEE_FRAMEWORKS } from './constant.js'; const hostMap = { @@ -98,3 +99,10 @@ export const getChainDefaults = ({ id, flavour }) => ({ }); export const isEnterpriseEnabled = (id) => !!enterpriseEnabledMap[id]; + +// register ethers unknown networks +const bellecourNetwork = new Network('bellecour', 134).attachPlugin( + new EnsPlugin(ensMap[134].registry, 134), +); +Network.register(134, () => bellecourNetwork); +Network.register('bellecour', () => bellecourNetwork); From 634467bdc627e6be8dfa1b6941390aae2e563ad0 Mon Sep 17 00:00:00 2001 From: Pierre Jeanjacquot <26487010+PierreJeanjacquot@users.noreply.github.com> Date: Fri, 19 Jul 2024 12:42:06 +0200 Subject: [PATCH 06/20] support for ethers AbstractProvider and AbstractSigner --- ...ner.md => BrowserProviderSignerAdapter.md} | 27 ++++--- docs/interfaces/IExecConfigArgs.md | 15 ++-- docs/modules.md | 2 +- src/common/utils/providers.js | 4 +- src/common/utils/signers.d.ts | 10 ++- src/common/utils/signers.js | 12 ++- src/lib/IExecConfig.d.ts | 25 ++++-- src/lib/IExecConfig.js | 81 ++++++++++--------- test/lib/e2e/IExecConfig.test.js | 57 +++++++++++++ 9 files changed, 163 insertions(+), 70 deletions(-) rename docs/classes/{BrowserProviderSigner.md => BrowserProviderSignerAdapter.md} (67%) diff --git a/docs/classes/BrowserProviderSigner.md b/docs/classes/BrowserProviderSignerAdapter.md similarity index 67% rename from docs/classes/BrowserProviderSigner.md rename to docs/classes/BrowserProviderSignerAdapter.md index 5b52f3f7..c4535388 100644 --- a/docs/classes/BrowserProviderSigner.md +++ b/docs/classes/BrowserProviderSignerAdapter.md @@ -1,43 +1,44 @@ -[iexec](../README.md) / [Exports](../modules.md) / BrowserProviderSigner +[iexec](../README.md) / [Exports](../modules.md) / BrowserProviderSignerAdapter -# Class: BrowserProviderSigner +# Class: BrowserProviderSignerAdapter + +BrowserProvider wrapped in an AbstractSigner ## Hierarchy - `AbstractSigner` - ↳ **`BrowserProviderSigner`** + ↳ **`BrowserProviderSignerAdapter`** ## Table of contents ### Constructors -- [constructor](BrowserProviderSigner.md#constructor) +- [constructor](BrowserProviderSignerAdapter.md#constructor) ### Methods -- [connect](BrowserProviderSigner.md#connect) -- [getAddress](BrowserProviderSigner.md#getaddress) -- [signMessage](BrowserProviderSigner.md#signmessage) -- [signTransaction](BrowserProviderSigner.md#signtransaction) -- [signTypedData](BrowserProviderSigner.md#signtypeddata) +- [connect](BrowserProviderSignerAdapter.md#connect) +- [getAddress](BrowserProviderSignerAdapter.md#getaddress) +- [signMessage](BrowserProviderSignerAdapter.md#signmessage) +- [signTransaction](BrowserProviderSignerAdapter.md#signtransaction) +- [signTypedData](BrowserProviderSignerAdapter.md#signtypeddata) ## Constructors ### constructor -• **new BrowserProviderSigner**(`ethereum`, `network?`): [`BrowserProviderSigner`](BrowserProviderSigner.md) +• **new BrowserProviderSignerAdapter**(`browserProvider`): [`BrowserProviderSignerAdapter`](BrowserProviderSignerAdapter.md) #### Parameters | Name | Type | | :------ | :------ | -| `ethereum` | `Eip1193Provider` | -| `network?` | `Networkish` | +| `browserProvider` | `BrowserProvider` | #### Returns -[`BrowserProviderSigner`](BrowserProviderSigner.md) +[`BrowserProviderSignerAdapter`](BrowserProviderSignerAdapter.md) #### Overrides diff --git a/docs/interfaces/IExecConfigArgs.md b/docs/interfaces/IExecConfigArgs.md index a34ed999..051c6362 100644 --- a/docs/interfaces/IExecConfigArgs.md +++ b/docs/interfaces/IExecConfigArgs.md @@ -13,15 +13,20 @@ ### ethProvider -• **ethProvider**: `string` \| `number` \| [`EnhancedWallet`](../classes/EnhancedWallet.md) \| [`Eip1193Provider`](Eip1193Provider.md) +• **ethProvider**: `string` \| `number` \| `AbstractSigner`<``null`` \| `Provider`\> \| `BrowserProvider` \| [`Eip1193Provider`](Eip1193Provider.md) \| `AbstractProvider` -A web3 Eth provider or network name or chain id +A web3 Eth provider, network name or chain id or an ethers provider -examples: -- `window.ethereum` -- `"mainnet"` or `1` or `"1"` for ethereum mainnet +read-only provider examples: +- `"mainnet"` or `1` or `"1"` for ethereum mainnet provider - `"bellecour"` or `134` or `"134"` for iExec sidechain - `"http://localhost:8545"` for local chain +- `new ethers.JsonRpcProvider("https://bellecour.iex.ec")` ethers provider connected to bellecour + +signer provider examples: +- `window.ethereum` for browser injected wallet provider +- `utils.getSignerFromPrivateKey('bellecour', PRIVATE_KEY)` signer connected to bellecour +- `new ethers.Wallet(PRIVATE_KEY, new ethers.JsonRpcProvider("https://bellecour.iex.ec"))` ethers wallet connected to bellecour ___ diff --git a/docs/modules.md b/docs/modules.md index e0f87a09..84fa7d9e 100644 --- a/docs/modules.md +++ b/docs/modules.md @@ -19,7 +19,7 @@ ### Classes -- [BrowserProviderSigner](classes/BrowserProviderSigner.md) +- [BrowserProviderSignerAdapter](classes/BrowserProviderSignerAdapter.md) - [EnhancedWallet](classes/EnhancedWallet.md) - [IExec](classes/IExec.md) - [IExecAccountModule](classes/IExecAccountModule.md) diff --git a/src/common/utils/providers.js b/src/common/utils/providers.js index 4d3135ce..c860a3bd 100644 --- a/src/common/utils/providers.js +++ b/src/common/utils/providers.js @@ -24,7 +24,9 @@ export const getReadOnlyProvider = (host, options = {}) => { } // RPC endpoint if (resolvedHost.startsWith('http')) { - return new JsonRpcProvider(resolvedHost, resolvedNetwork); + return new JsonRpcProvider(resolvedHost, resolvedNetwork, { + pollingInterval: 1000, // override default 4s for faster tx confirms (TODO: default value per network + option) + }); } // API provider const { quorum, ...providersOptionsRest } = providerOptions; diff --git a/src/common/utils/signers.d.ts b/src/common/utils/signers.d.ts index 766887f6..54a8c05f 100644 --- a/src/common/utils/signers.d.ts +++ b/src/common/utils/signers.d.ts @@ -6,10 +6,9 @@ import { AbstractSigner, Signer, TransactionRequest, - Eip1193Provider, - Networkish, TypedDataDomain, TypedDataField, + BrowserProvider, } from 'ethers'; export class EnhancedWallet extends Wallet { @@ -23,8 +22,11 @@ export class EnhancedWallet extends Wallet { ); } -export class BrowserProviderSigner extends AbstractSigner { - constructor(ethereum: Eip1193Provider, network?: Networkish); +/** + * BrowserProvider wrapped in an AbstractSigner + */ +export class BrowserProviderSignerAdapter extends AbstractSigner { + constructor(browserProvider: BrowserProvider); getAddress(): Promise; connect(provider: Provider | null): Signer; signMessage(message: string | Uint8Array): Promise; diff --git a/src/common/utils/signers.js b/src/common/utils/signers.js index 5aea61ce..ff0ac7e6 100644 --- a/src/common/utils/signers.js +++ b/src/common/utils/signers.js @@ -52,9 +52,15 @@ export class EnhancedWallet extends Wallet { } } -export class BrowserProviderSigner extends AbstractSigner { - constructor(...args) { - super(new BrowserProvider(...args)); +/** + * BrowserProvider wrapped in an AbstractSigner + */ +export class BrowserProviderSignerAdapter extends AbstractSigner { + constructor(browserProvider) { + if (!(browserProvider instanceof BrowserProvider)) { + throw Error('Invalid BrowserProvider'); + } + super(browserProvider); } getAddress() { diff --git a/src/lib/IExecConfig.d.ts b/src/lib/IExecConfig.d.ts index 77a1f4b1..82ba89d1 100644 --- a/src/lib/IExecConfig.d.ts +++ b/src/lib/IExecConfig.d.ts @@ -4,6 +4,8 @@ export type * from './IExecConfig.js'; import IExecContractsClient from '../common/utils/IExecContractsClient.js'; import { EnhancedWallet } from '../common/utils/signers.js'; import { AnyRecord, ProviderOptions, TeeFramework } from '../common/types.js'; +import { AbstractProvider, AbstractSigner } from 'ethers'; +import { BrowserProvider } from 'ethers'; export interface Eip1193Provider { request(request: { @@ -13,15 +15,26 @@ export interface Eip1193Provider { } export interface IExecConfigArgs { /** - * A web3 Eth provider or network name or chain id + * A web3 Eth provider, network name or chain id or an ethers provider * - * examples: - * - `window.ethereum` - * - `"mainnet"` or `1` or `"1"` for ethereum mainnet + * read-only provider examples: + * - `"mainnet"` or `1` or `"1"` for ethereum mainnet provider * - `"bellecour"` or `134` or `"134"` for iExec sidechain * - `"http://localhost:8545"` for local chain - */ - ethProvider: Eip1193Provider | EnhancedWallet | string | number; + * - `new ethers.JsonRpcProvider("https://bellecour.iex.ec")` ethers provider connected to bellecour + * + * signer provider examples: + * - `window.ethereum` for browser injected wallet provider + * - `utils.getSignerFromPrivateKey('bellecour', PRIVATE_KEY)` signer connected to bellecour + * - `new ethers.Wallet(PRIVATE_KEY, new ethers.JsonRpcProvider("https://bellecour.iex.ec"))` ethers wallet connected to bellecour + */ + ethProvider: + | Eip1193Provider + | AbstractProvider + | AbstractSigner + | BrowserProvider + | string + | number; /** * flavour to use (default standard) */ diff --git a/src/lib/IExecConfig.js b/src/lib/IExecConfig.js index 7a9a57bb..1797cd73 100644 --- a/src/lib/IExecConfig.js +++ b/src/lib/IExecConfig.js @@ -1,17 +1,14 @@ import Debug from 'debug'; -import { JsonRpcProvider, BrowserProvider } from 'ethers'; +import { BrowserProvider, AbstractProvider, AbstractSigner } from 'ethers'; import IExecContractsClient from '../common/utils/IExecContractsClient.js'; import { ConfigurationError } from '../common/utils/errors.js'; -import { - EnhancedWallet, - BrowserProviderSigner, -} from '../common/utils/signers.js'; import { getChainDefaults, isEnterpriseEnabled, } from '../common/utils/config.js'; import { TEE_FRAMEWORKS } from '../common/utils/constant.js'; import { getReadOnlyProvider } from '../common/utils/providers.js'; +import { BrowserProviderSignerAdapter } from '../common/utils/signers.js'; import { smsUrlOrMapSchema, teeFrameworkSchema, @@ -47,15 +44,42 @@ export default class IExecConfig { ) { throw new ConfigurationError('Missing ethProvider'); } - const isReadOnlyProvider = + + /** + * JSON RPC provider, API providers, Browser provider (polling option) + */ + const isEthersAbstractProvider = ethProvider instanceof AbstractProvider; + /** + * Browser provider is abstract signer with getSigner + */ + const isEthersBrowserProvider = ethProvider instanceof BrowserProvider; + /** + * Wallet, JSON RPC signer may have a provider + */ + const isEthersAbstractSigner = ethProvider instanceof AbstractSigner; + /** + * Wallet, JSON RPC signer with a provider + */ + const isEthersAbstractSignerWithProvider = + isEthersAbstractSigner && ethProvider.provider; + if (isEthersAbstractSigner && !isEthersAbstractSignerWithProvider) { + throw new ConfigurationError('Missing provider for ethProvider signer'); + } + + /** + * RPC url, chain name/id + */ + const isRpcUrlProvider = typeof ethProvider === 'string' || typeof ethProvider === 'number'; - const isEnhancedWalletProvider = ethProvider instanceof EnhancedWallet; + // used to get chain id and and find additional config let disposableProvider; try { - if (isEnhancedWalletProvider) { + if (isEthersAbstractProvider) { + disposableProvider = ethProvider; + } else if (isEthersAbstractSignerWithProvider) { disposableProvider = ethProvider.provider; - } else if (isReadOnlyProvider) { + } else if (isRpcUrlProvider) { disposableProvider = getReadOnlyProvider(ethProvider, { providers: providerOptions, }); @@ -121,39 +145,22 @@ export default class IExecConfig { ...chainDefaults.network, ...(ensRegistryAddress && { ensAddress: ensRegistryAddress }), }; - if (isEnhancedWalletProvider) { - if (ethProvider.provider instanceof JsonRpcProvider) { - // case JsonRpcProvider - signer = ethProvider.connect( - new JsonRpcProvider( - // eslint-disable-next-line no-underscore-dangle - ethProvider.provider._getConnection().url, - networkOverride, - { pollingInterval: 1000 }, // override default polling interval (4000) for faster confirmation - ), - ); - } else { - // case FallbackProvider can not override - if (ensRegistryAddress) { - console.warn( - 'IExec: ensRegistryAddress option is not supported when using a default provider', - ); - } - signer = ethProvider; - } - provider = signer.provider; - } else if (isReadOnlyProvider) { + if (isRpcUrlProvider) { provider = getReadOnlyProvider(ethProvider, { providers: providerOptions, network: networkOverride, }); + } else if (isEthersAbstractSignerWithProvider) { + provider = ethProvider.provider; + signer = ethProvider; + } else if (isEthersAbstractProvider) { + provider = ethProvider; + if (isEthersBrowserProvider) { + signer = new BrowserProviderSignerAdapter(ethProvider); + } } else { - const browserSigner = new BrowserProviderSigner( - ethProvider, - networkOverride, - ); - signer = browserSigner; - provider = browserSigner.provider; + provider = new BrowserProvider(ethProvider, networkOverride); + signer = new BrowserProviderSignerAdapter(provider); } return { provider, signer }; })(); diff --git a/test/lib/e2e/IExecConfig.test.js b/test/lib/e2e/IExecConfig.test.js index 6c2d19d1..39e130b0 100644 --- a/test/lib/e2e/IExecConfig.test.js +++ b/test/lib/e2e/IExecConfig.test.js @@ -9,6 +9,8 @@ import { EtherscanProvider, CloudflareProvider, BrowserProvider, + Wallet, + HDNodeWallet, } from 'ethers'; import { ALCHEMY_API_KEY, @@ -487,6 +489,61 @@ describe('[IExecConfig]', () => { }); }); + describe('ethers AbstractProvider', () => { + test('JsonRpcProvider', async () => { + const ethersProvider = new JsonRpcProvider(iexecTestChain.rpcURL); + const config = new IExecConfig({ + ethProvider: ethersProvider, + }); + const { provider, signer, chainId } = + await config.resolveContractsClient(); + expect(signer).toBeUndefined(); + expect(provider).toBeDefined(); + expect(provider).toBeInstanceOf(JsonRpcProvider); + expect(chainId).toBe(iexecTestChain.chainId); + const network = await provider.getNetwork(); + expect(network.chainId).toBe(BigInt(iexecTestChain.chainId)); + expect(network.name).toBe(iexecTestChain.defaults.name); + expect( + network.getPlugin('org.ethers.plugins.network.Ens').address, + ).toBe(iexecTestChain.defaults.ensRegistryAddress); + }); + }); + + describe('ethers AbstractSigner', () => { + test('throw if no provider is connected', async () => { + const ethersSigner = Wallet.createRandom(); + const createConfig = () => + new IExecConfig({ ethProvider: ethersSigner }); + expect(createConfig).toThrow( + Error('Missing provider for ethProvider signer'), + ); + expect(createConfig).toThrow(errors.ConfigurationError); + }); + + test('Wallet with provider', async () => { + const ethersSigner = Wallet.createRandom( + new JsonRpcProvider(iexecTestChain.rpcURL), + ); + const config = new IExecConfig({ + ethProvider: ethersSigner, + }); + const { provider, signer, chainId } = + await config.resolveContractsClient(); + expect(signer).toBeDefined(); + expect(signer).toBeInstanceOf(HDNodeWallet); + expect(provider).toBeDefined(); + expect(provider).toBeInstanceOf(JsonRpcProvider); + expect(chainId).toBe(iexecTestChain.chainId); + const network = await provider.getNetwork(); + expect(network.chainId).toBe(BigInt(iexecTestChain.chainId)); + expect(network.name).toBe(iexecTestChain.defaults.name); + expect( + network.getPlugin('org.ethers.plugins.network.Ens').address, + ).toBe(iexecTestChain.defaults.ensRegistryAddress); + }); + }); + describe('bridged chain provider', () => { test('IExecConfig({ ethProvider: "bellecour" })', async () => { const config = new IExecConfig({ ethProvider: 'bellecour' }); From 27acedd21f821637ab7697e082b1b498e30ddd39 Mon Sep 17 00:00:00 2001 From: Pierre Jeanjacquot <26487010+PierreJeanjacquot@users.noreply.github.com> Date: Fri, 19 Jul 2024 12:44:04 +0200 Subject: [PATCH 07/20] refactor hardcoded --- src/common/utils/config.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/common/utils/config.js b/src/common/utils/config.js index 91ecdac4..1d939975 100644 --- a/src/common/utils/config.js +++ b/src/common/utils/config.js @@ -101,8 +101,8 @@ export const getChainDefaults = ({ id, flavour }) => ({ export const isEnterpriseEnabled = (id) => !!enterpriseEnabledMap[id]; // register ethers unknown networks -const bellecourNetwork = new Network('bellecour', 134).attachPlugin( +const bellecourNetwork = new Network(networkMap[134].name, 134).attachPlugin( new EnsPlugin(ensMap[134].registry, 134), ); -Network.register(134, () => bellecourNetwork); -Network.register('bellecour', () => bellecourNetwork); +Network.register(bellecourNetwork.chainId, () => bellecourNetwork); +Network.register(bellecourNetwork.name, () => bellecourNetwork); From d639d5e6d47cd23bc0cef33a4956a20747b7373f Mon Sep 17 00:00:00 2001 From: Pierre Jeanjacquot <26487010+PierreJeanjacquot@users.noreply.github.com> Date: Fri, 19 Jul 2024 16:54:47 +0200 Subject: [PATCH 08/20] fix test issues due to fast polling --- test/cli/cli-iexec-deal.test.js | 3 +++ test/cli/cli-iexec-task.test.js | 2 ++ test/lib/e2e/workflow.test.js | 3 +++ 3 files changed, 8 insertions(+) diff --git a/test/cli/cli-iexec-deal.test.js b/test/cli/cli-iexec-deal.test.js index 1179bb5d..48fd2a57 100644 --- a/test/cli/cli-iexec-deal.test.js +++ b/test/cli/cli-iexec-deal.test.js @@ -6,6 +6,7 @@ import { adminCreateCategory, execAsync, initializeTask, + sleep, } from '../test-utils'; import { globalSetup, @@ -48,6 +49,7 @@ describe('iexec deal', () => { dealid = await runIExecCliRaw( `${iexecPath} app run ${userApp.address} --workerpool ${userWorkerpool.address} --dataset ${userDataset.address} --category ${noDurationCatid} --force`, ).then((res) => res.deals[0].dealid); + await sleep(5000); // wait for next block to be added (deal timeout) }); afterAll(async () => { @@ -124,6 +126,7 @@ describe('iexec deal', () => { const claimableDealid = await runIExecCliRaw( `${iexecPath} app run ${userApp.address} --workerpool ${userWorkerpool.address} --dataset ${userDataset.address} --category ${noDurationCatid} --force`, ).then((res) => res.deals[0].dealid); + await sleep(5000); // wait for next block to be added const res = await runIExecCliRaw( `${iexecPath} deal claim ${claimableDealid}`, ); diff --git a/test/cli/cli-iexec-task.test.js b/test/cli/cli-iexec-task.test.js index aea401b7..7e6feb4b 100644 --- a/test/cli/cli-iexec-task.test.js +++ b/test/cli/cli-iexec-task.test.js @@ -7,6 +7,7 @@ import { execAsync, initializeTask, adminCreateCategory, + sleep, } from '../test-utils'; import { globalSetup, @@ -125,6 +126,7 @@ describe('iexec task', () => { const dealid = await runIExecCliRaw( `${iexecPath} app run ${userApp.address} --workerpool ${userWorkerpool.address} --dataset ${userDataset.address} --category ${noDurationCatid} --force`, ).then((res) => res.deals[0].dealid); + await sleep(5000); // wait for next block to be added const taskid = await runIExecCliRaw( `${iexecPath} deal show ${dealid}`, ).then((res) => res.deal.tasks[0]); diff --git a/test/lib/e2e/workflow.test.js b/test/lib/e2e/workflow.test.js index 6e4e08dd..a7550a6d 100644 --- a/test/lib/e2e/workflow.test.js +++ b/test/lib/e2e/workflow.test.js @@ -9,6 +9,7 @@ import { getId, initializeTask, setNRlcBalance, + sleep, } from '../../test-utils'; import '../../jest-setup'; import { errors } from '../../../src/lib'; @@ -243,6 +244,8 @@ describe('[workflow]', () => { expect(matchOrdersRes.txHash).toBeDefined(); expect(matchOrdersRes.volume.eq(new BN(10))).toBe(true); + await sleep(5000); // wait for next block to be added + const showDealRes = await iexec.deal.show(matchOrdersRes.dealid); expect(showDealRes).toBeDefined(); expect(showDealRes.app).toBeDefined(); From 35d16737bc7bf331d8033d9a59930e24c89d2523 Mon Sep 17 00:00:00 2001 From: Pierre Jeanjacquot <26487010+PierreJeanjacquot@users.noreply.github.com> Date: Fri, 19 Jul 2024 16:55:18 +0200 Subject: [PATCH 09/20] remove ensRegistryAddress option --- CHANGELOG.md | 1 + docs/interfaces/IExecConfigOptions.md | 9 ----- src/common/utils/config.js | 1 - src/common/utils/providers.js | 9 +---- src/lib/IExecConfig.d.ts | 4 -- src/lib/IExecConfig.js | 13 +------ test/lib/e2e/IExecConfig.test.js | 53 +++++++++++++++------------ test/lib/e2e/utils.test.js | 4 +- 8 files changed, 34 insertions(+), 60 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b6829dc6..626aa91d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ All notable changes to this project will be documented in this file. ## NEXT +- removed `ensRegistryAddress` option (use ethers `Network.register()` to configure custom networks supporting ENS) - more permissive url validation for `iexec_input_files` ## [8.9.1] 2024-06-19 diff --git a/docs/interfaces/IExecConfigOptions.md b/docs/interfaces/IExecConfigOptions.md index f0a9ae19..68049bc4 100644 --- a/docs/interfaces/IExecConfigOptions.md +++ b/docs/interfaces/IExecConfigOptions.md @@ -11,7 +11,6 @@ - [confirms](IExecConfigOptions.md#confirms) - [defaultTeeFramework](IExecConfigOptions.md#defaultteeframework) - [ensPublicResolverAddress](IExecConfigOptions.md#enspublicresolveraddress) -- [ensRegistryAddress](IExecConfigOptions.md#ensregistryaddress) - [enterpriseSwapConf](IExecConfigOptions.md#enterpriseswapconf) - [hubAddress](IExecConfigOptions.md#hubaddress) - [iexecGatewayURL](IExecConfigOptions.md#iexecgatewayurl) @@ -73,14 +72,6 @@ override the ENS public resolver contract address to target a custom instance ___ -### ensRegistryAddress - -• `Optional` **ensRegistryAddress**: `string` - -override the ENS registry contract address to target a custom instance - -___ - ### enterpriseSwapConf • `Optional` **enterpriseSwapConf**: `Object` diff --git a/src/common/utils/config.js b/src/common/utils/config.js index 1d939975..f95f1b9b 100644 --- a/src/common/utils/config.js +++ b/src/common/utils/config.js @@ -95,7 +95,6 @@ export const getChainDefaults = ({ id, flavour }) => ({ iexecGateway: iexecGatewayMap[flavour] && iexecGatewayMap[flavour][id], bridge: bridgeMap[flavour] && bridgeMap[flavour][id], flavour, - network: networkMap[id], }); export const isEnterpriseEnabled = (id) => !!enterpriseEnabledMap[id]; diff --git a/src/common/utils/providers.js b/src/common/utils/providers.js index c860a3bd..c3b61c1f 100644 --- a/src/common/utils/providers.js +++ b/src/common/utils/providers.js @@ -3,7 +3,6 @@ import { getChainDefaults, getId } from './config.js'; export const getReadOnlyProvider = (host, options = {}) => { const providerOptions = options.providers || {}; - const networkOptions = options.network; let resolvedHost = host; const defaults = getChainDefaults({ id: getId(host) }); @@ -18,13 +17,9 @@ export const getReadOnlyProvider = (host, options = {}) => { throw Error('Invalid provider host name or url'); } - let resolvedNetwork = networkOptions; - if (!resolvedNetwork && defaults && defaults.network) { - resolvedNetwork = defaults.network; - } // RPC endpoint if (resolvedHost.startsWith('http')) { - return new JsonRpcProvider(resolvedHost, resolvedNetwork, { + return new JsonRpcProvider(resolvedHost, undefined, { pollingInterval: 1000, // override default 4s for faster tx confirms (TODO: default value per network + option) }); } @@ -44,7 +39,7 @@ export const getReadOnlyProvider = (host, options = {}) => { const nonConfiguredProviders = apiProvidersList.filter( (apiProvider) => !Object.keys(providersOptionsRest).includes(apiProvider), ); - return getDefaultProvider(resolvedNetwork || resolvedHost, { + return getDefaultProvider(resolvedHost, { quorum: quorum || 1, ...(nonConfiguredProviders.length < apiProvidersList.length && Object.fromEntries(nonConfiguredProviders.map((name) => [name, '-']))), diff --git a/src/lib/IExecConfig.d.ts b/src/lib/IExecConfig.d.ts index 82ba89d1..d7d0ccb0 100644 --- a/src/lib/IExecConfig.d.ts +++ b/src/lib/IExecConfig.d.ts @@ -54,10 +54,6 @@ export interface IExecConfigOptions { * override the IExec contract address to target a custom instance */ hubAddress?: string; - /** - * override the ENS registry contract address to target a custom instance - */ - ensRegistryAddress?: string; /** * override the ENS public resolver contract address to target a custom instance */ diff --git a/src/lib/IExecConfig.js b/src/lib/IExecConfig.js index 1797cd73..7294868a 100644 --- a/src/lib/IExecConfig.js +++ b/src/lib/IExecConfig.js @@ -21,7 +21,6 @@ export default class IExecConfig { { ethProvider, flavour = 'standard' } = {}, { hubAddress, - ensRegistryAddress, ensPublicResolverAddress, isNative, useGas = true, @@ -138,17 +137,9 @@ export default class IExecConfig { const providerAndSignerPromise = (async () => { let provider; let signer; - const network = await networkPromise; - const chainDefaults = await chainConfDefaultsPromise; - const networkOverride = { - ...network, - ...chainDefaults.network, - ...(ensRegistryAddress && { ensAddress: ensRegistryAddress }), - }; if (isRpcUrlProvider) { provider = getReadOnlyProvider(ethProvider, { providers: providerOptions, - network: networkOverride, }); } else if (isEthersAbstractSignerWithProvider) { provider = ethProvider.provider; @@ -159,7 +150,7 @@ export default class IExecConfig { signer = new BrowserProviderSignerAdapter(ethProvider); } } else { - provider = new BrowserProvider(ethProvider, networkOverride); + provider = new BrowserProvider(ethProvider); signer = new BrowserProviderSignerAdapter(provider); } return { provider, signer }; @@ -285,7 +276,6 @@ export default class IExecConfig { flavour === 'standard' ? !contracts.isNative : contracts.isNative, hubAddress: bridgedNetworkConf.hubAddress, bridgeAddress: bridgedBridgeAddress, - network: bridgedChainConfDefaults.network, }; })(); @@ -300,7 +290,6 @@ export default class IExecConfig { chainId: bridgedConf.chainId, provider: getReadOnlyProvider(bridgedConf.rpcURL, { providers: providerOptions, - network: bridgedConf.network, }), hubAddress: bridgedConf.hubAddress, confirms, diff --git a/test/lib/e2e/IExecConfig.test.js b/test/lib/e2e/IExecConfig.test.js index 39e130b0..9d7aead7 100644 --- a/test/lib/e2e/IExecConfig.test.js +++ b/test/lib/e2e/IExecConfig.test.js @@ -387,30 +387,6 @@ describe('[IExecConfig]', () => { }); }); - describe('read-only ethProvider with ens override', () => { - test('IExecConfig({ ethProvider: "http://localhost:8545" }, { hubAddress, ensRegistryAddress })', async () => { - const config = new IExecConfig( - { ethProvider: unknownTestChain.rpcURL }, - { - hubAddress: unknownTestChain.hubAddress, - ensRegistryAddress: unknownTestChain.ensRegistryAddress, - }, - ); - const { provider, signer, chainId } = - await config.resolveContractsClient(); - expect(signer).toBeUndefined(); - expect(provider).toBeDefined(); - expect(provider).toBeInstanceOf(JsonRpcProvider); - expect(chainId).toBe(unknownTestChain.chainId); - const network = await provider.getNetwork(); - expect(network.chainId).toBe(BigInt(unknownTestChain.chainId)); - expect(network.name).toBe('unknown'); - expect( - network.getPlugin('org.ethers.plugins.network.Ens').address, - ).toBe(unknownTestChain.ensRegistryAddress); - }); - }); - describe('signer provider from private key', () => { test('getSignerFromPrivateKey()', async () => { const wallet = getRandomWallet(); @@ -508,6 +484,35 @@ describe('[IExecConfig]', () => { network.getPlugin('org.ethers.plugins.network.Ens').address, ).toBe(iexecTestChain.defaults.ensRegistryAddress); }); + + test('JsonRpcProvider with custom network (including ens)', async () => { + const ethersProvider = new JsonRpcProvider(unknownTestChain.rpcURL, { + chainId: parseInt(unknownTestChain.chainId, 10), + name: 'test', + ensAddress: unknownTestChain.ensRegistryAddress, + }); + const config = new IExecConfig( + { + ethProvider: ethersProvider, + }, + { + hubAddress: unknownTestChain.hubAddress, + ensRegistryAddress: unknownTestChain.ensRegistryAddress, + }, + ); + const { provider, signer, chainId } = + await config.resolveContractsClient(); + expect(signer).toBeUndefined(); + expect(provider).toBeDefined(); + expect(provider).toBeInstanceOf(JsonRpcProvider); + expect(chainId).toBe(unknownTestChain.chainId); + const network = await provider.getNetwork(); + expect(network.chainId).toBe(BigInt(unknownTestChain.chainId)); + expect(network.name).toBe('test'); + expect( + network.getPlugin('org.ethers.plugins.network.Ens').address, + ).toBe(unknownTestChain.ensRegistryAddress); + }); }); describe('ethers AbstractSigner', () => { diff --git a/test/lib/e2e/utils.test.js b/test/lib/e2e/utils.test.js index 892eadb1..d438ffca 100644 --- a/test/lib/e2e/utils.test.js +++ b/test/lib/e2e/utils.test.js @@ -336,9 +336,7 @@ describe('utils', () => { getTestConfigOptions(tokenTestChain)(), ); await setBalance(tokenTestChain)(wallet.address, ONE_ETH); - const { registerTxHash: txHash } = await iexec.ens.claimName( - `name-${getId()}`, - ); + const txHash = await iexec.wallet.sendETH(0, wallet.address); const tx = await tokenTestChain.provider.getTransaction(txHash); expect(tx).toBeDefined(); expect(tx.gasPrice.toString()).toBe(gasPrice); From 565bb55c47413c52ca50b269d79950ed8863eb88 Mon Sep 17 00:00:00 2001 From: Pierre Jeanjacquot <26487010+PierreJeanjacquot@users.noreply.github.com> Date: Fri, 19 Jul 2024 16:55:38 +0200 Subject: [PATCH 10/20] use ethers provider in tests --- test/lib/lib-test-utils.js | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/test/lib/lib-test-utils.js b/test/lib/lib-test-utils.js index b0106a92..51d221ec 100644 --- a/test/lib/lib-test-utils.js +++ b/test/lib/lib-test-utils.js @@ -1,7 +1,7 @@ // @jest/global comes with jest // eslint-disable-next-line import/no-extraneous-dependencies import { expect } from '@jest/globals'; -import { Wallet } from 'ethers'; +import { JsonRpcProvider, Wallet } from 'ethers'; import { NULL_ADDRESS, TEE_FRAMEWORKS, @@ -9,9 +9,7 @@ import { getRandomWallet, sleep, } from '../test-utils'; -import { IExec, utils } from '../../src/lib'; - -const { getSignerFromPrivateKey } = utils; +import { IExec } from '../../src/lib'; export const ONE_ETH = 10n ** 18n; @@ -50,11 +48,11 @@ export const getTestConfig = iexec: new IExec({ ethProvider: chain.rpcURL }, configOptions), }; } + const provider = new JsonRpcProvider(chain.rpcURL, undefined, { + pollingInterval: 1000, + }); const wallet = privateKey ? new Wallet(privateKey) : getRandomWallet(); - const ethProvider = getSignerFromPrivateKey( - chain.rpcURL, - wallet.privateKey, - ); + const ethProvider = new Wallet(wallet.privateKey, provider); return { iexec: new IExec({ ethProvider }, configOptions), wallet, From 99ba5415e88745abbeb6a6fa08359fcc67c46cf0 Mon Sep 17 00:00:00 2001 From: Pierre Jeanjacquot <26487010+PierreJeanjacquot@users.noreply.github.com> Date: Fri, 19 Jul 2024 16:59:04 +0200 Subject: [PATCH 11/20] update changelog --- CHANGELOG.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 626aa91d..481f4620 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,9 +4,19 @@ All notable changes to this project will be documented in this file. ## NEXT -- removed `ensRegistryAddress` option (use ethers `Network.register()` to configure custom networks supporting ENS) +### Added + +- added support for ethers `AbstractProvider`, `AbstractSigner` and `BrowserProvider` to instantiate modules + +### Changed + +- reduced default polling interval for faster tx confirms - more permissive url validation for `iexec_input_files` +### Removed + +- removed `ensRegistryAddress` option (use ethers `Network.register()` to configure custom networks supporting ENS) + ## [8.9.1] 2024-06-19 ### Changed From 806e651e2da3559a0f79015a7274d14c212fd213 Mon Sep 17 00:00:00 2001 From: Pierre Jeanjacquot <26487010+PierreJeanjacquot@users.noreply.github.com> Date: Mon, 22 Jul 2024 09:49:34 +0200 Subject: [PATCH 12/20] clean useless legacy code --- src/lib/IExecConfig.js | 54 ++++++++++++------------------------------ 1 file changed, 15 insertions(+), 39 deletions(-) diff --git a/src/lib/IExecConfig.js b/src/lib/IExecConfig.js index 7294868a..ad595f92 100644 --- a/src/lib/IExecConfig.js +++ b/src/lib/IExecConfig.js @@ -71,20 +71,25 @@ export default class IExecConfig { const isRpcUrlProvider = typeof ethProvider === 'string' || typeof ethProvider === 'number'; - // used to get chain id and and find additional config - let disposableProvider; + let provider; + let signer; try { - if (isEthersAbstractProvider) { - disposableProvider = ethProvider; - } else if (isEthersAbstractSignerWithProvider) { - disposableProvider = ethProvider.provider; - } else if (isRpcUrlProvider) { - disposableProvider = getReadOnlyProvider(ethProvider, { + if (isRpcUrlProvider) { + provider = getReadOnlyProvider(ethProvider, { providers: providerOptions, }); + } else if (isEthersAbstractSignerWithProvider) { + provider = ethProvider.provider; + signer = ethProvider; + } else if (isEthersAbstractProvider) { + provider = ethProvider; + if (isEthersBrowserProvider) { + signer = new BrowserProviderSignerAdapter(ethProvider); + } } else { try { - disposableProvider = new BrowserProvider(ethProvider); + provider = new BrowserProvider(ethProvider); + signer = new BrowserProviderSignerAdapter(provider); } catch (err) { debug('BrowserProvider', err); throw Error('Unsupported provider'); @@ -93,7 +98,6 @@ export default class IExecConfig { } catch (err) { throw new ConfigurationError(`Invalid ethProvider: ${err.message}`); } - let vSmsUrlOrMap; try { vSmsUrlOrMap = smsUrlOrMapSchema().validateSync(smsURL); @@ -112,7 +116,7 @@ export default class IExecConfig { } const networkPromise = (async () => { - const network = await disposableProvider.getNetwork().catch((err) => { + const network = await provider.getNetwork().catch((err) => { throw Error(`Failed to detect network: ${err.message}`); }); const { chainId, name } = network; @@ -134,35 +138,8 @@ export default class IExecConfig { debug('chainConfDefaultsPromise', err); }); - const providerAndSignerPromise = (async () => { - let provider; - let signer; - if (isRpcUrlProvider) { - provider = getReadOnlyProvider(ethProvider, { - providers: providerOptions, - }); - } else if (isEthersAbstractSignerWithProvider) { - provider = ethProvider.provider; - signer = ethProvider; - } else if (isEthersAbstractProvider) { - provider = ethProvider; - if (isEthersBrowserProvider) { - signer = new BrowserProviderSignerAdapter(ethProvider); - } - } else { - provider = new BrowserProvider(ethProvider); - signer = new BrowserProviderSignerAdapter(provider); - } - return { provider, signer }; - })(); - - providerAndSignerPromise.catch((err) => { - debug('providerAndSignerPromise', err); - }); - const contractsPromise = (async () => { const { chainId } = await networkPromise; - const { provider, signer } = await providerAndSignerPromise; try { return new IExecContractsClient({ chainId, @@ -187,7 +164,6 @@ export default class IExecConfig { const enterpriseSwapContractsPromise = (async () => { const { chainId } = await networkPromise; - const { provider, signer } = await providerAndSignerPromise; const hasEnterpriseConf = enterpriseSwapConf.hubAddress || isEnterpriseEnabled(chainId); if (!hasEnterpriseConf) { From 90fa30374b13b51f6afa86e83e42ec4aa9cbb7d5 Mon Sep 17 00:00:00 2001 From: Pierre Jeanjacquot <26487010+PierreJeanjacquot@users.noreply.github.com> Date: Mon, 22 Jul 2024 10:40:18 +0200 Subject: [PATCH 13/20] remove ensRegistry from chain.json --- src/cli/utils/chains.js | 32 ++++++-------------------------- src/cli/utils/fs.js | 2 +- src/common/utils/config.js | 1 - test/cli/cli-test-utils.js | 1 - 4 files changed, 7 insertions(+), 29 deletions(-) diff --git a/src/cli/utils/chains.js b/src/cli/utils/chains.js index 0cf576c7..1b2813f9 100644 --- a/src/cli/utils/chains.js +++ b/src/cli/utils/chains.js @@ -1,5 +1,4 @@ import Debug from 'debug'; -import { JsonRpcProvider } from 'ethers'; import { getChainDefaults, isEnterpriseEnabled, @@ -38,18 +37,9 @@ const createChainFromConf = ( ) => { try { const chain = { ...chainConf }; - const provider = - chainConf.host && chainConf.host.indexOf('http') === 0 - ? new JsonRpcProvider( - chainConf.host, - { - ensAddress: chainConf.ensRegistry, - chainId: parseInt(chainConf.id, 10), - name: chainName, - }, - { pollingInterval: 1000 }, // override default polling interval (4000) for faster confirmation - ) - : getReadOnlyProvider(chainConf.host, { providers: providerOptions }); + const provider = getReadOnlyProvider(chainConf.host, { + providers: providerOptions, + }); chain.name = chainName; const contracts = new IExecContractsClient({ @@ -64,19 +54,9 @@ const createChainFromConf = ( chain.contracts = contracts; if (bridgeConf) { chain.bridgedNetwork = { ...bridgeConf }; - const bridgeProvider = - bridgeConf.host && bridgeConf.host.indexOf('http') === 0 - ? new JsonRpcProvider( - bridgeConf.host, - { - ensAddress: bridgeConf.ensRegistry, - chainId: parseInt(bridgeConf.id, 10), - }, - { pollingInterval: 1000 }, // override default polling interval (4000) for faster confirmation) - ) - : getReadOnlyProvider(bridgeConf.host, { - providers: providerOptions, - }); + const bridgeProvider = getReadOnlyProvider(bridgeConf.host, { + providers: providerOptions, + }); chain.bridgedNetwork.contracts = new IExecContractsClient({ provider: bridgeProvider, chainId: bridgeConf.id, diff --git a/src/cli/utils/fs.js b/src/cli/utils/fs.js index 52f3ffaa..aaa69d2e 100644 --- a/src/cli/utils/fs.js +++ b/src/cli/utils/fs.js @@ -26,7 +26,7 @@ const chainConfSchema = () => id: chainIdSchema(), host: string(), hub: string(), // todo address - ensRegistry: string(), // todo address + ensRegistry: string(), // TODO: DEPRECATED not used anymore ensPublicResolver: string(), // todo address sms: smsUrlOrMapSchema(), resultProxy: string(), diff --git a/src/common/utils/config.js b/src/common/utils/config.js index f95f1b9b..9f5671d2 100644 --- a/src/common/utils/config.js +++ b/src/common/utils/config.js @@ -88,7 +88,6 @@ export const getChainDefaults = ({ id, flavour }) => ({ host: hostMap[id], hub: hubMap[flavour] && hubMap[flavour][id], sms: smsMap[flavour] && smsMap[flavour][id], - ensRegistry: ensMap[id] && ensMap[id].registry, ensPublicResolver: ensMap[id] && ensMap[id].publicResolver, resultProxy: resultProxyMap[flavour] && resultProxyMap[flavour][id], ipfsGateway: ipfsGatewayMap[flavour] && ipfsGatewayMap[flavour][id], diff --git a/test/cli/cli-test-utils.js b/test/cli/cli-test-utils.js index 34e2f34d..9e0644a6 100644 --- a/test/cli/cli-test-utils.js +++ b/test/cli/cli-test-utils.js @@ -72,7 +72,6 @@ export const setChain = sms: chain.smsMap, iexecGateway: chain.iexecGatewayURL, resultProxy: chain.resultProxyURL, - ensRegistry: chain.ensRegistryAddress, ensPublicResolver: chain.ensPublicResolverAddress, useGas: chain.useGas, native: chain.isNative, From d1527233e882ebf261be77129a7ac99ff779c00e Mon Sep 17 00:00:00 2001 From: Pierre Jeanjacquot <26487010+PierreJeanjacquot@users.noreply.github.com> Date: Mon, 22 Jul 2024 10:58:04 +0200 Subject: [PATCH 14/20] clean old gateways --- README.md | 3 --- docs/README.md | 1 - src/cli/cmd/iexec-orderbook.js | 4 ---- typedoc_template.md | 1 - 4 files changed, 9 deletions(-) diff --git a/README.md b/README.md index 07736af9..5fd84660 100644 --- a/README.md +++ b/README.md @@ -85,7 +85,4 @@ Find changes in the [CHANGELOG](./CHANGELOG.md) ## Resources - [iExec main documentation](https://docs.iex.ec/for-developers/) -- [The iExec Dapp Store](https://dapps.iex.ec) -- [The iExec Marketplace](https://market.iex.ec) - [The iExec Explorer](https://explorer.iex.ec) -- [The iExec Workerpool registry](https://pools.iex.ec) diff --git a/docs/README.md b/docs/README.md index f6c3d73b..c922621f 100644 --- a/docs/README.md +++ b/docs/README.md @@ -4,7 +4,6 @@ iexec / [Exports](modules.md) # iExec SDK Library API -[![Build Status](https://drone.iex.ec/api/badges/iExecBlockchainComputing/iexec-sdk/status.svg)](https://drone.iex.ec/iExecBlockchainComputing/iexec-sdk) [![npm version](https://badge.fury.io/js/iexec.svg)](https://www.npmjs.com/package/iexec) [![npm version](https://img.shields.io/npm/dm/iexec.svg)](https://www.npmjs.com/package/iexec) [![license](https://img.shields.io/github/license/iExecBlockchainComputing/iexec-sdk.svg)](LICENSE) Use the iExec decentralized marketplace for off-chain computing in your dapp. diff --git a/src/cli/cmd/iexec-orderbook.js b/src/cli/cmd/iexec-orderbook.js index b06ea2af..6c07d592 100644 --- a/src/cli/cmd/iexec-orderbook.js +++ b/src/cli/cmd/iexec-orderbook.js @@ -136,7 +136,6 @@ orderbookApp appOrders: results, }, }); - spinner.info('Trade in the browser at https://market.iex.ec'); } catch (error) { handleError(error, cli, opts); } @@ -251,7 +250,6 @@ orderbookDataset datasetOrders: results, }, }); - spinner.info('Trade in the browser at https://market.iex.ec'); } catch (error) { handleError(error, cli, opts); } @@ -379,7 +377,6 @@ orderbookWorkerpool workerpoolOrders: results, }, }); - spinner.info('Trade in the browser at https://market.iex.ec'); } catch (error) { handleError(error, cli, opts); } @@ -500,7 +497,6 @@ orderbookRequester requestOrders: results, }, }); - spinner.info('Trade in the browser at https://market.iex.ec'); } catch (error) { handleError(error, cli, opts); } diff --git a/typedoc_template.md b/typedoc_template.md index 9edbc84f..acb6c834 100644 --- a/typedoc_template.md +++ b/typedoc_template.md @@ -2,7 +2,6 @@ # iExec SDK Library API -[![Build Status](https://drone.iex.ec/api/badges/iExecBlockchainComputing/iexec-sdk/status.svg)](https://drone.iex.ec/iExecBlockchainComputing/iexec-sdk) [![npm version](https://badge.fury.io/js/iexec.svg)](https://www.npmjs.com/package/iexec) [![npm version](https://img.shields.io/npm/dm/iexec.svg)](https://www.npmjs.com/package/iexec) [![license](https://img.shields.io/github/license/iExecBlockchainComputing/iexec-sdk.svg)](LICENSE) Use the iExec decentralized marketplace for off-chain computing in your dapp. From b3c45b8abf81a3f16feca9d14b8cea83ef1c54b5 Mon Sep 17 00:00:00 2001 From: Pierre Jeanjacquot <26487010+PierreJeanjacquot@users.noreply.github.com> Date: Mon, 22 Jul 2024 11:04:56 +0200 Subject: [PATCH 15/20] remove registry commands --- CLI.md | 32 ----- package-lock.json | 33 ----- package.json | 1 - src/cli/cmd/iexec-registry.js | 233 ---------------------------------- src/cli/cmd/iexec.js | 2 - src/cli/utils/cli-helper.js | 2 - 6 files changed, 303 deletions(-) delete mode 100644 src/cli/cmd/iexec-registry.js diff --git a/CLI.md b/CLI.md index a28e6796..98a94559 100644 --- a/CLI.md +++ b/CLI.md @@ -314,7 +314,6 @@ Commands: - [iexec result](#iexec-result) - [iexec ens](#iexec-ens) - [iexec category](#iexec-category) -- [iexec registry](#iexec-registry) - [info](#iexec-info) ### iexec init @@ -2453,37 +2452,6 @@ Options: | --quiet | stop prompting updates | | --chain \ | chain name from "chain.json" | -### iexec registry - -interact with iExec registry - -Usage: - -```sh -iexec registry [options] -``` - -Commands: - -- [validate](#iexec-registry-validate) - -#### iexec registry validate - -validate an app/dataset/workerpool description before submitting it to the iExec registry - -Usage: - -```sh -iexec registry validate [options] -``` - -Options: - -| option | description | -| --- | --- | -| --raw | use raw output | -| --quiet | stop prompting updates | - ### iexec info show iExec contracts addresses diff --git a/package-lock.json b/package-lock.json index 64dff490..92b533b5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,7 +19,6 @@ "debug": "^4.3.4", "ethers": "^6.8.0", "fs-extra": "^11.1.1", - "image-size": "^1.0.2", "inquirer": "^9.2.11", "is-docker": "^3.0.0", "jszip": "^3.10.1", @@ -3813,19 +3812,6 @@ "node": ">= 4" } }, - "node_modules/image-size": { - "version": "1.0.2", - "license": "MIT", - "dependencies": { - "queue": "6.0.2" - }, - "bin": { - "image-size": "bin/image-size.js" - }, - "engines": { - "node": ">=14.0.0" - } - }, "node_modules/immediate": { "version": "3.0.6", "license": "MIT" @@ -5998,13 +5984,6 @@ "node": ">=14.16" } }, - "node_modules/queue": { - "version": "6.0.2", - "license": "MIT", - "dependencies": { - "inherits": "~2.0.3" - } - }, "node_modules/queue-microtask": { "version": "1.2.3", "dev": true, @@ -10060,12 +10039,6 @@ "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", "dev": true }, - "image-size": { - "version": "1.0.2", - "requires": { - "queue": "6.0.2" - } - }, "immediate": { "version": "3.0.6" }, @@ -11558,12 +11531,6 @@ } } }, - "queue": { - "version": "6.0.2", - "requires": { - "inherits": "~2.0.3" - } - }, "queue-microtask": { "version": "1.2.3", "dev": true diff --git a/package.json b/package.json index 4d2c22a0..0e221b8c 100644 --- a/package.json +++ b/package.json @@ -199,7 +199,6 @@ "debug": "^4.3.4", "ethers": "^6.8.0", "fs-extra": "^11.1.1", - "image-size": "^1.0.2", "inquirer": "^9.2.11", "is-docker": "^3.0.0", "jszip": "^3.10.1", diff --git a/src/cli/cmd/iexec-registry.js b/src/cli/cmd/iexec-registry.js deleted file mode 100644 index 986142c9..00000000 --- a/src/cli/cmd/iexec-registry.js +++ /dev/null @@ -1,233 +0,0 @@ -#!/usr/bin/env node - -import { program as cli } from 'commander'; -import Debug from 'debug'; -import fsExtra from 'fs-extra'; -import { object, array, string } from 'yup'; -import sizeOf from 'image-size'; -import { join, extname } from 'path'; -import { - chainIdSchema, - addressSchema, - bytes32Schema, - appTypeSchema, - uint256Schema, - mrenclaveSchema, -} from '../../common/utils/validator.js'; -import { - finalizeCli, - addGlobalOptions, - checkUpdate, - handleError, - desc, - Spinner, - pretty, -} from '../utils/cli-helper.js'; -import { - loadDeployedConf, - loadIExecConf, - IEXEC_FILE_NAME, - DEPLOYED_FILE_NAME, -} from '../utils/fs.js'; -import { - APP, - DATASET, - WORKERPOOL, - IEXEC_REQUEST_PARAMS, -} from '../../common/utils/constant.js'; - -const { readFile } = fsExtra; - -const debug = Debug('iexec:iexec-registry'); - -const addressListSchema = () => - object().test(async (value) => { - await Promise.all( - Object.entries({ ...value }).map(async ([chainId, address]) => { - await chainIdSchema().validate(chainId); - await addressSchema().validate(address); - }), - ); - return true; - }); - -const baseSchema = () => - object({ - type: string(), - description: string().min(150).max(2000).required(), - logo: string().required(), - social: object({ - website: string(), - github: string(), - }).required(), - repo: string(), - }); - -const buyConfSchema = () => - object({ - params: object({ - [IEXEC_REQUEST_PARAMS.IEXEC_ARGS]: string(), - }) - .required() - .noUnknown() - .strict(), - trust: uint256Schema(), - tag: bytes32Schema(), - callback: addressSchema(), - }); - -const dappSchema = () => - baseSchema() - .shape({ - license: string().required(), - author: string().required(), - app: object({ - owner: addressSchema().required(), - name: string().required(), - type: appTypeSchema().required(), - multiaddr: string().required(), - checksum: bytes32Schema().required(), - mrenclave: mrenclaveSchema(), - }).required(), - buyConf: buyConfSchema().required(), - }) - .noUnknown() - .strict(); - -const datasetCompatibleDappSchema = () => - object({ - name: string().required(), - addresses: addressListSchema().required(), - buyConf: buyConfSchema(), - }); - -const datasetSchema = () => - baseSchema() - .shape({ - license: string().required(), - author: string().required(), - categories: string(), - dataset: object({ - owner: addressSchema().required(), - name: string().required(), - multiaddr: string().required(), - checksum: bytes32Schema().required(), - }).required(), - dapps: array().of(datasetCompatibleDappSchema()), - }) - .noUnknown() - .strict(); - -const workerpoolSchema = () => - baseSchema() - .shape({ - workerpool: object({ - owner: addressSchema().required(), - description: string().required(), - }).required(), - }) - .noUnknown() - .strict(); - -cli.name('iexec registry').usage(' [options]'); - -const LOGO_SIDE = 180; -const repo = 'https://github.com/iExecBlockchainComputing/'; -const objectNames = [APP, WORKERPOOL, DATASET]; -const objectMap = { - [APP]: { - name: APP, - validationSchema: dappSchema, - registry: repo.concat('iexec-dapps-registry'), - }, - [DATASET]: { - name: DATASET, - validationSchema: datasetSchema, - registry: repo.concat('iexec-datasets-registry'), - }, - [WORKERPOOL]: { - name: WORKERPOOL, - validationSchema: workerpoolSchema, - registry: repo.concat('iexec-pools-registry'), - }, -}; - -const validate = cli.command('validate '); -addGlobalOptions(validate); -validate.description(desc.validateResource()).action(async (objName, opts) => { - await checkUpdate(opts); - const spinner = Spinner(opts); - try { - if (!objectNames.includes(objName)) { - throw Error( - `Unknown object "${objName}". Must be one of [${objectNames}]`, - ); - } - const objectName = objectMap[objName].name; - // validate iexec.json - const iexecConf = await loadIExecConf(); - const validated = []; - const failed = []; - try { - await objectMap[objName] - .validationSchema() - .validate(iexecConf, { strict: true }); - validated.push(IEXEC_FILE_NAME); - } catch (confError) { - failed.push(`${IEXEC_FILE_NAME}: ${confError.message}`); - } - // validate logo file - const logoPath = join(process.cwd(), iexecConf.logo); - let logoFile; - try { - logoFile = await readFile(logoPath); - const logoSize = sizeOf(logoFile); - debug('logoSize', logoSize); - if (!(logoSize.width === LOGO_SIDE && logoSize.height === LOGO_SIDE)) { - throw Error( - `${iexecConf.logo} dimensions should be ${LOGO_SIDE}px by ${LOGO_SIDE}px, NOT ${logoSize.width} by ${logoSize.height}`, - ); - } - const logoExt = extname(iexecConf.logo).substr(1); - if (!(logoSize.type === logoExt)) { - throw Error(`Extension mismatch: ${logoSize.type} =/= ${logoExt}`); - } - validated.push(iexecConf.logo); - } catch (logoError) { - const errorMessage = - logoError.code === 'ENOENT' - ? `Missing "${iexecConf.logo}" logo image file` - : logoError.message; - failed.push(`${iexecConf.logo}: ${errorMessage}`); - } - - // validate deployed.json - try { - const deployedObj = await loadDeployedConf(); - if (!(objectName in deployedObj)) { - throw Error( - `Missing ${objectName} field. You should run "iexec ${objName} deploy"`, - ); - } - validated.push(DEPLOYED_FILE_NAME); - } catch (confError) { - failed.push(`${DEPLOYED_FILE_NAME}: ${confError.message}`); - } - if (failed.length === 0) { - spinner.succeed( - `${objName} description is valid. You can now submit it to the ${objName} registry: ${objectMap[objName].registry}`, - { - raw: { validated }, - }, - ); - } else { - spinner.fail(`Invalid files: ${pretty(failed)}`, { - raw: { validated, fail: failed }, - }); - } - } catch (error) { - handleError(error, cli, opts); - } -}); - -finalizeCli(cli); diff --git a/src/cli/cmd/iexec.js b/src/cli/cmd/iexec.js index 00e9384d..5117d4ca 100755 --- a/src/cli/cmd/iexec.js +++ b/src/cli/cmd/iexec.js @@ -109,8 +109,6 @@ cli.command('ens', 'manage ENS names'); cli.command('category', 'manage iExec categories'); -cli.command('registry', 'interact with iExec registry'); - const infoCmd = cli.command('info'); addGlobalOptions(infoCmd); infoCmd diff --git a/src/cli/utils/cli-helper.js b/src/cli/utils/cli-helper.js index ec4f940b..0fd47d45 100644 --- a/src/cli/utils/cli-helper.js +++ b/src/cli/utils/cli-helper.js @@ -124,8 +124,6 @@ export const desc = { '[DEPRECATED see send-RLC] send RLC to an address (WARNING! default unit nRLC)', sweep: () => 'send all ether and RLC to an address', info: () => 'show iExec contracts addresses', - validateResource: () => - 'validate an app/dataset/workerpool description before submitting it to the iExec registry', decrypt: () => 'decrypt work result', sign: () => 'sign orders from "iexec.json" and store them into "orders.json"', cancelOrder: (objName) => `cancel a signed ${objName}`, From abda085571fa1f886f5aa4e5723b730f51244517 Mon Sep 17 00:00:00 2001 From: Pierre Jeanjacquot <26487010+PierreJeanjacquot@users.noreply.github.com> Date: Mon, 22 Jul 2024 11:13:27 +0200 Subject: [PATCH 16/20] update changelog --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b6829dc6..20911843 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,8 +4,14 @@ All notable changes to this project will be documented in this file. ## NEXT +### Changed + - more permissive url validation for `iexec_input_files` +### Removed + +- CLI removed `iexec registry` commands + ## [8.9.1] 2024-06-19 ### Changed From 83959195eee417e0186da382969cf1461f062039 Mon Sep 17 00:00:00 2001 From: pjt <26487010+PierreJeanjacquot@users.noreply.github.com> Date: Tue, 23 Jul 2024 12:02:54 +0200 Subject: [PATCH 17/20] merge import source Co-authored-by: Cedric Nicoloso --- src/lib/IExecConfig.d.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/lib/IExecConfig.d.ts b/src/lib/IExecConfig.d.ts index d7d0ccb0..384a74b5 100644 --- a/src/lib/IExecConfig.d.ts +++ b/src/lib/IExecConfig.d.ts @@ -4,8 +4,7 @@ export type * from './IExecConfig.js'; import IExecContractsClient from '../common/utils/IExecContractsClient.js'; import { EnhancedWallet } from '../common/utils/signers.js'; import { AnyRecord, ProviderOptions, TeeFramework } from '../common/types.js'; -import { AbstractProvider, AbstractSigner } from 'ethers'; -import { BrowserProvider } from 'ethers'; +import { AbstractProvider, AbstractSigner, BrowserProvider } from 'ethers'; export interface Eip1193Provider { request(request: { From ea7779cbb2844b7e4e0dfec57612f1bfa7dfd346 Mon Sep 17 00:00:00 2001 From: Pierre Jeanjacquot <26487010+PierreJeanjacquot@users.noreply.github.com> Date: Tue, 23 Jul 2024 12:06:46 +0200 Subject: [PATCH 18/20] changelog wording --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5fd3ca75..2f2d7949 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,7 @@ All notable changes to this project will be documented in this file. ### Changed -- reduced default polling interval for faster tx confirms +- reduced default polling interval for faster tx confirmation - more permissive url validation for `iexec_input_files` ### Removed From d4dc6aa6bc009a0c514003a0985c1eff329a5d28 Mon Sep 17 00:00:00 2001 From: Pierre Jeanjacquot <26487010+PierreJeanjacquot@users.noreply.github.com> Date: Tue, 23 Jul 2024 12:08:41 +0200 Subject: [PATCH 19/20] ethProvider description --- docs/interfaces/IExecConfigArgs.md | 2 +- src/lib/IExecConfig.d.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/interfaces/IExecConfigArgs.md b/docs/interfaces/IExecConfigArgs.md index 051c6362..2172c7c8 100644 --- a/docs/interfaces/IExecConfigArgs.md +++ b/docs/interfaces/IExecConfigArgs.md @@ -15,7 +15,7 @@ • **ethProvider**: `string` \| `number` \| `AbstractSigner`<``null`` \| `Provider`\> \| `BrowserProvider` \| [`Eip1193Provider`](Eip1193Provider.md) \| `AbstractProvider` -A web3 Eth provider, network name or chain id or an ethers provider +A web3 Eth provider, a network name, a chain id or an ethers provider read-only provider examples: - `"mainnet"` or `1` or `"1"` for ethereum mainnet provider diff --git a/src/lib/IExecConfig.d.ts b/src/lib/IExecConfig.d.ts index 384a74b5..24864088 100644 --- a/src/lib/IExecConfig.d.ts +++ b/src/lib/IExecConfig.d.ts @@ -14,7 +14,7 @@ export interface Eip1193Provider { } export interface IExecConfigArgs { /** - * A web3 Eth provider, network name or chain id or an ethers provider + * A web3 Eth provider, a network name, a chain id or an ethers provider * * read-only provider examples: * - `"mainnet"` or `1` or `"1"` for ethereum mainnet provider From 9ad3451d37b75b4baeee275dbabc72268cde2be3 Mon Sep 17 00:00:00 2001 From: Pierre Jeanjacquot <26487010+PierreJeanjacquot@users.noreply.github.com> Date: Wed, 24 Jul 2024 14:16:03 +0200 Subject: [PATCH 20/20] bump v8.10.0 --- CHANGELOG.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- src/common/generated/sdk/package.js | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2f2d7949..fdaf1715 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ All notable changes to this project will be documented in this file. -## NEXT +## [8.10.0] 2024-07-24 ### Added diff --git a/package-lock.json b/package-lock.json index 5c69d3ab..a922198c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "iexec", - "version": "8.9.1", + "version": "8.10.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "iexec", - "version": "8.9.1", + "version": "8.10.0", "license": "Apache-2.0", "dependencies": { "@ensdomains/ens-contracts": "^0.0.22", diff --git a/package.json b/package.json index 3c53cce2..6b14b4ad 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "iexec", - "version": "8.9.1", + "version": "8.10.0", "description": "iExec SDK", "bin": { "iexec": "./dist/esm/cli/cmd/iexec.js" diff --git a/src/common/generated/sdk/package.js b/src/common/generated/sdk/package.js index 376126c0..3c51745f 100644 --- a/src/common/generated/sdk/package.js +++ b/src/common/generated/sdk/package.js @@ -1,6 +1,6 @@ // this file is auto generated do not edit it /* eslint-disable */ export const name = "iexec"; -export const version = "8.9.1"; +export const version = "8.10.0"; export const description = "iExec SDK"; export default { name, version, description }; \ No newline at end of file