From df9ded51b84534607c94180a5c2842ecdc598822 Mon Sep 17 00:00:00 2001 From: bunsenstraat Date: Tue, 20 Aug 2024 11:18:52 +0200 Subject: [PATCH 01/67] remixd flaky test --- .circleci/config.yml | 2 +- apps/remix-ide-e2e/src/tests/remixd.test.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index d5a065c41d..a95ed97b6b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -3,7 +3,7 @@ version: 2.1 parameters: run_flaky_tests: type: boolean - default: false + default: true orbs: browser-tools: circleci/browser-tools@1.4.4 win: circleci/windows@5.0 diff --git a/apps/remix-ide-e2e/src/tests/remixd.test.ts b/apps/remix-ide-e2e/src/tests/remixd.test.ts index 6fb821820a..529a77b71b 100644 --- a/apps/remix-ide-e2e/src/tests/remixd.test.ts +++ b/apps/remix-ide-e2e/src/tests/remixd.test.ts @@ -66,7 +66,7 @@ module.exports = { '@sources': function () { return sources }, - 'run Remixd tests #group1': function (browser) { + 'run Remixd tests #group1 #flaky': function (browser) { browser.perform(async (done) => { try { remixd = await spawnRemixd(join(process.cwd(), '/apps/remix-ide', '/contracts')) From de79b46977eff8a678fb5cd0f9af691d33239010 Mon Sep 17 00:00:00 2001 From: bunsenstraat Date: Tue, 20 Aug 2024 11:49:35 +0200 Subject: [PATCH 02/67] flaky failed test --- apps/remix-ide-e2e/src/tests/ballot.test.ts | 4 ++-- apps/remix-ide-e2e/src/tests/remixd.test.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/remix-ide-e2e/src/tests/ballot.test.ts b/apps/remix-ide-e2e/src/tests/ballot.test.ts index c9fb7c27bc..656a90414b 100644 --- a/apps/remix-ide-e2e/src/tests/ballot.test.ts +++ b/apps/remix-ide-e2e/src/tests/ballot.test.ts @@ -20,10 +20,10 @@ module.exports = { browser .addFile('Untitled.sol', sources[0]['Untitled.sol']) }, - 'Deploy Ballot #group1': function (browser: NightwatchBrowser) { + 'Deploy Ballot #group1 #flaky': function (browser: NightwatchBrowser) { browser .waitForElementVisible('*[data-id="remixIdeIconPanel"]', 10000) - .clickLaunchIcon('solidity') + .clickLaunchIcon('solidity2') .testContracts('Untitled.sol', sources[0]['Untitled.sol'], ['Ballot']) .clickLaunchIcon('udapp') .selectAccount('0xCA35b7d915458EF540aDe6068dFe2F44E8fa733c') diff --git a/apps/remix-ide-e2e/src/tests/remixd.test.ts b/apps/remix-ide-e2e/src/tests/remixd.test.ts index 529a77b71b..6fb821820a 100644 --- a/apps/remix-ide-e2e/src/tests/remixd.test.ts +++ b/apps/remix-ide-e2e/src/tests/remixd.test.ts @@ -66,7 +66,7 @@ module.exports = { '@sources': function () { return sources }, - 'run Remixd tests #group1 #flaky': function (browser) { + 'run Remixd tests #group1': function (browser) { browser.perform(async (done) => { try { remixd = await spawnRemixd(join(process.cwd(), '/apps/remix-ide', '/contracts')) From b23dc4bde544ec1eb3767184610f659f6be88a5c Mon Sep 17 00:00:00 2001 From: bunsenstraat Date: Tue, 20 Aug 2024 12:00:44 +0200 Subject: [PATCH 03/67] rerun flaky --- apps/remix-ide/ci/flaky.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/remix-ide/ci/flaky.sh b/apps/remix-ide/ci/flaky.sh index 5373daec0b..69c7bbe734 100755 --- a/apps/remix-ide/ci/flaky.sh +++ b/apps/remix-ide/ci/flaky.sh @@ -23,7 +23,7 @@ yarn run serve:production & sleep 5 for TESTFILE in $TESTFILES; do - npx nightwatch --config dist/apps/remix-ide-e2e/nightwatch-${1}.js $TESTFILE --env=$1 || TEST_EXITCODE=1 + npx nightwatch --config dist/apps/remix-ide-e2e/nightwatch-${1}.js $TESTFILE --env=$1 || npx nightwatch --config dist/apps/remix-ide-e2e/nightwatch-${1}.js $TESTFILE --env=$1 || TEST_EXITCODE=1 done echo "$TEST_EXITCODE" From 13b942902daa0ad14792544febe11a357b2dfb67 Mon Sep 17 00:00:00 2001 From: bunsenstraat Date: Tue, 20 Aug 2024 12:15:34 +0200 Subject: [PATCH 04/67] remixd --- apps/remix-ide-e2e/src/tests/ballot.test.ts | 2 +- apps/remix-ide-e2e/src/tests/remixd.test.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/remix-ide-e2e/src/tests/ballot.test.ts b/apps/remix-ide-e2e/src/tests/ballot.test.ts index 656a90414b..d97a362ea3 100644 --- a/apps/remix-ide-e2e/src/tests/ballot.test.ts +++ b/apps/remix-ide-e2e/src/tests/ballot.test.ts @@ -20,7 +20,7 @@ module.exports = { browser .addFile('Untitled.sol', sources[0]['Untitled.sol']) }, - 'Deploy Ballot #group1 #flaky': function (browser: NightwatchBrowser) { + 'Deploy Ballot #group1': function (browser: NightwatchBrowser) { browser .waitForElementVisible('*[data-id="remixIdeIconPanel"]', 10000) .clickLaunchIcon('solidity2') diff --git a/apps/remix-ide-e2e/src/tests/remixd.test.ts b/apps/remix-ide-e2e/src/tests/remixd.test.ts index 6fb821820a..529a77b71b 100644 --- a/apps/remix-ide-e2e/src/tests/remixd.test.ts +++ b/apps/remix-ide-e2e/src/tests/remixd.test.ts @@ -66,7 +66,7 @@ module.exports = { '@sources': function () { return sources }, - 'run Remixd tests #group1': function (browser) { + 'run Remixd tests #group1 #flaky': function (browser) { browser.perform(async (done) => { try { remixd = await spawnRemixd(join(process.cwd(), '/apps/remix-ide', '/contracts')) From 9d2c0c62d6840e8c8ad61f2b3503f68427ea723a Mon Sep 17 00:00:00 2001 From: bunsenstraat Date: Wed, 21 Aug 2024 15:04:20 +0200 Subject: [PATCH 05/67] more checks --- apps/remix-ide-e2e/src/tests/remixd.test.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/remix-ide-e2e/src/tests/remixd.test.ts b/apps/remix-ide-e2e/src/tests/remixd.test.ts index 529a77b71b..323d779fc5 100644 --- a/apps/remix-ide-e2e/src/tests/remixd.test.ts +++ b/apps/remix-ide-e2e/src/tests/remixd.test.ts @@ -322,8 +322,10 @@ function runTests(browser: NightwatchBrowser, done: any) { .setEditorValue('contract test1Changed { function get () returns (uint) { return 10; }}') .testEditorValue('contract test1Changed { function get () returns (uint) { return 10; }}') .setEditorValue('contract test1 { function get () returns (uint) { return 10; }}') + .waitForElementVisible('[data-path="folder1/contract_' + browserName + '.sol"]') .click('[data-path="folder1/contract_' + browserName + '.sol"]') // rename a file and check .pause(1000) + .saveScreenshot('./reports/screenshots/remixd1.png') .renamePath('folder1/contract_' + browserName + '.sol', 'renamed_contract_' + browserName, 'folder1/renamed_contract_' + browserName + '.sol') .pause(1000) .removeFile('folder1/contract_' + browserName + '_toremove.sol', 'localhost') From b6fb99130cace3de61ec45718acc1aa67d3727dc Mon Sep 17 00:00:00 2001 From: bunsenstraat Date: Wed, 21 Aug 2024 15:33:45 +0200 Subject: [PATCH 06/67] run aftereach --- apps/remix-ide-e2e/src/tests/remixd.test.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/apps/remix-ide-e2e/src/tests/remixd.test.ts b/apps/remix-ide-e2e/src/tests/remixd.test.ts index 323d779fc5..a234c6a4b6 100644 --- a/apps/remix-ide-e2e/src/tests/remixd.test.ts +++ b/apps/remix-ide-e2e/src/tests/remixd.test.ts @@ -55,6 +55,10 @@ module.exports = { before: function (browser, done) { init(browser, done) }, + afterEach: function (browser, done) { + console.log('afterEach') + done() + }, after: function (browser) { browser.perform((done) => { console.log('remixd', remixd.pid) @@ -322,6 +326,7 @@ function runTests(browser: NightwatchBrowser, done: any) { .setEditorValue('contract test1Changed { function get () returns (uint) { return 10; }}') .testEditorValue('contract test1Changed { function get () returns (uint) { return 10; }}') .setEditorValue('contract test1 { function get () returns (uint) { return 10; }}') + .waitForElementVisible('[data-path="folder1"]') .waitForElementVisible('[data-path="folder1/contract_' + browserName + '.sol"]') .click('[data-path="folder1/contract_' + browserName + '.sol"]') // rename a file and check .pause(1000) From 11b5366179afd4897cc6cb64bd47c56fe6aefb1d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 21 Aug 2024 13:04:38 +0000 Subject: [PATCH 07/67] Bump elliptic from 6.5.4 to 6.5.7 in /apps/remix-ide-e2e Bumps [elliptic](https://github.com/indutny/elliptic) from 6.5.4 to 6.5.7. - [Commits](https://github.com/indutny/elliptic/compare/v6.5.4...v6.5.7) --- updated-dependencies: - dependency-name: elliptic dependency-type: indirect ... Signed-off-by: dependabot[bot] --- apps/remix-ide-e2e/yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/remix-ide-e2e/yarn.lock b/apps/remix-ide-e2e/yarn.lock index ec987d4405..8355207ece 100644 --- a/apps/remix-ide-e2e/yarn.lock +++ b/apps/remix-ide-e2e/yarn.lock @@ -923,9 +923,9 @@ ejs@3.1.8: jake "^10.8.5" elliptic@^6.5.4: - version "6.5.4" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" - integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== + version "6.5.7" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.7.tgz#8ec4da2cb2939926a1b9a73619d768207e647c8b" + integrity sha512-ESVCtTwiA+XhY3wyh24QqRGBoP3rEdDUl3EDUUo9tft074fi19IrdpH7hLCMMP3CIj7jb3W96rn8lt/BqIlt5Q== dependencies: bn.js "^4.11.9" brorand "^1.1.0" From 84f102091bc86a149680664627a343e68689e185 Mon Sep 17 00:00:00 2001 From: bunsenstraat Date: Wed, 21 Aug 2024 16:01:03 +0200 Subject: [PATCH 08/67] spawn kill --- apps/remix-ide-e2e/src/tests/remixd.test.ts | 41 ++++++++++++++++++--- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/apps/remix-ide-e2e/src/tests/remixd.test.ts b/apps/remix-ide-e2e/src/tests/remixd.test.ts index a234c6a4b6..5b07e5bfa9 100644 --- a/apps/remix-ide-e2e/src/tests/remixd.test.ts +++ b/apps/remix-ide-e2e/src/tests/remixd.test.ts @@ -55,15 +55,25 @@ module.exports = { before: function (browser, done) { init(browser, done) }, - afterEach: function (browser, done) { - console.log('afterEach') - done() + afterEach: async function (browser, done) { + if (browser.currentTest.results.failed > 0) { + // Perform actions if the test case failed + console.log('Test failed, disconnecting services...'); + console.log('remixd', remixd.pid) + } + done(); }, after: function (browser) { - browser.perform((done) => { + console.log('after') + browser.perform(async (done) => { console.log('remixd', remixd.pid) - kill(remixd.pid) + try { + await killProcess(remixd.pid) + }catch(e){ + + } done() + browser.end() }) }, @@ -402,6 +412,27 @@ async function spawnRemixd(path: string): Promise { }) } +function killProcess(pid, signal = 'SIGKILL') { + return new Promise((resolve, reject) => { + const kill = spawn('kill', ['-s', signal, pid]); + + kill.on('close', (code) => { + if (code === 0) { + console.log(`Successfully killed process with PID: ${pid}`); + resolve(); + } else { + console.error(`Failed to kill process with PID: ${pid}. Exit code: ${code}`); + reject(new Error(`kill process failed with code ${code}`)); + } + }); + + kill.on('error', (err) => { + console.error(`Error spawning kill process: ${err.message}`); + reject(err); + }); + }); +} + function connectRemixd(browser: NightwatchBrowser, done: any) { const browserName = browser.options.desiredCapabilities.browserName if (browserName === 'safari' || browserName === 'internet explorer') { From 7537b70f53320dbc4af8672d365f1809de475160 Mon Sep 17 00:00:00 2001 From: bunsenstraat Date: Wed, 21 Aug 2024 16:32:45 +0200 Subject: [PATCH 09/67] refactor --- apps/remix-ide-e2e/src/tests/remixd.test.ts | 33 +++++++++++---------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/apps/remix-ide-e2e/src/tests/remixd.test.ts b/apps/remix-ide-e2e/src/tests/remixd.test.ts index 5b07e5bfa9..7f518abb54 100644 --- a/apps/remix-ide-e2e/src/tests/remixd.test.ts +++ b/apps/remix-ide-e2e/src/tests/remixd.test.ts @@ -55,26 +55,27 @@ module.exports = { before: function (browser, done) { init(browser, done) }, - afterEach: async function (browser, done) { + afterEach: async function (browser) { if (browser.currentTest.results.failed > 0) { - // Perform actions if the test case failed console.log('Test failed, disconnecting services...'); - console.log('remixd', remixd.pid) - } - done(); - }, - after: function (browser) { - console.log('after') - browser.perform(async (done) => { - console.log('remixd', remixd.pid) + console.log('remixd', remixd.pid); + try { - await killProcess(remixd.pid) - }catch(e){ - + await killProcess(remixd.pid); + console.log('Service disconnected successfully.'); + } catch (error) { + console.error('Failed to disconnect service:', error); } - done() - browser.end() - }) + } + }, + + after: async function (browser) { + try { + await killProcess(remixd.pid); + console.log('Service disconnected successfully.'); + } catch (error) { + console.error('Failed to disconnect service:', error); + } }, '@sources': function () { From b8b43e4812d0c84d7d350ceecaae91d1b9e7439a Mon Sep 17 00:00:00 2001 From: bunsenstraat Date: Wed, 21 Aug 2024 17:18:01 +0200 Subject: [PATCH 10/67] try another way --- apps/remix-ide-e2e/src/tests/remixd.test.ts | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/apps/remix-ide-e2e/src/tests/remixd.test.ts b/apps/remix-ide-e2e/src/tests/remixd.test.ts index 7f518abb54..51c4c61f24 100644 --- a/apps/remix-ide-e2e/src/tests/remixd.test.ts +++ b/apps/remix-ide-e2e/src/tests/remixd.test.ts @@ -6,6 +6,7 @@ import { ChildProcess, spawn } from 'child_process' import { homedir } from 'os' import kill from 'tree-kill' +import treeKill from 'tree-kill' let remixd: ChildProcess const assetsTestContract = `import "./contract.sol"; @@ -59,19 +60,15 @@ module.exports = { if (browser.currentTest.results.failed > 0) { console.log('Test failed, disconnecting services...'); console.log('remixd', remixd.pid); - - try { - await killProcess(remixd.pid); - console.log('Service disconnected successfully.'); - } catch (error) { - console.error('Failed to disconnect service:', error); - } } }, after: async function (browser) { try { - await killProcess(remixd.pid); + console.log('remixd pid', remixd.pid); + treeKill(remixd.pid, 'SIGKILL', (err) => { + console.log('remixd killed', err) + }) console.log('Service disconnected successfully.'); } catch (error) { console.error('Failed to disconnect service:', error); From 9d60c853d277ef8123a0fb99061ce8d0277dc792 Mon Sep 17 00:00:00 2001 From: bunsenstraat Date: Wed, 21 Aug 2024 17:46:43 +0200 Subject: [PATCH 11/67] no async --- apps/remix-ide-e2e/src/tests/remixd.test.ts | 31 ++++++++++----------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/apps/remix-ide-e2e/src/tests/remixd.test.ts b/apps/remix-ide-e2e/src/tests/remixd.test.ts index 51c4c61f24..994d44d18f 100644 --- a/apps/remix-ide-e2e/src/tests/remixd.test.ts +++ b/apps/remix-ide-e2e/src/tests/remixd.test.ts @@ -56,23 +56,20 @@ module.exports = { before: function (browser, done) { init(browser, done) }, - afterEach: async function (browser) { - if (browser.currentTest.results.failed > 0) { - console.log('Test failed, disconnecting services...'); - console.log('remixd', remixd.pid); - } - }, - - after: async function (browser) { - try { - console.log('remixd pid', remixd.pid); - treeKill(remixd.pid, 'SIGKILL', (err) => { - console.log('remixd killed', err) - }) - console.log('Service disconnected successfully.'); - } catch (error) { - console.error('Failed to disconnect service:', error); - } + + after: function (browser) { + browser.perform((done) => { + try { + console.log('remixd pid', remixd.pid); + treeKill(remixd.pid, 'SIGKILL', (err) => { + console.log('remixd killed', err) + }) + console.log('Service disconnected successfully.'); + } catch (error) { + console.error('Failed to disconnect service:', error); + } + done() + }) }, '@sources': function () { From 283a1432046e4cb3080bd7b6f1a5084ee8593527 Mon Sep 17 00:00:00 2001 From: bunsenstraat Date: Wed, 21 Aug 2024 18:00:41 +0200 Subject: [PATCH 12/67] fix rename path --- apps/remix-ide-e2e/src/commands/renamePath.ts | 28 +++++----- apps/remix-ide-e2e/src/tests/remixd.test.ts | 52 +++++++++++++++---- 2 files changed, 58 insertions(+), 22 deletions(-) diff --git a/apps/remix-ide-e2e/src/commands/renamePath.ts b/apps/remix-ide-e2e/src/commands/renamePath.ts index d87faf7261..7ac7606631 100644 --- a/apps/remix-ide-e2e/src/commands/renamePath.ts +++ b/apps/remix-ide-e2e/src/commands/renamePath.ts @@ -2,7 +2,7 @@ import EventEmitter from 'events' import { NightwatchBrowser } from 'nightwatch' class RenamePath extends EventEmitter { - command (this: NightwatchBrowser, path: string, newFileName: string, renamedPath: string) { + command(this: NightwatchBrowser, path: string, newFileName: string, renamedPath: string) { this.api.perform((done) => { renamePath(this.api, path, newFileName, renamedPath, () => { done() @@ -13,9 +13,9 @@ class RenamePath extends EventEmitter { } } -function renamePath (browser: NightwatchBrowser, path: string, newFileName: string, renamedPath: string, done: VoidFunction) { +function renamePath(browser: NightwatchBrowser, path: string, newFileName: string, renamedPath: string, done: VoidFunction) { browser.execute(function (path: string) { - function contextMenuClick (element) { + function contextMenuClick(element) { const evt = element.ownerDocument.createEvent('MouseEvents') const RIGHT_CLICK_BUTTON_CODE = 2 // the same for FF and IE @@ -32,15 +32,19 @@ function renamePath (browser: NightwatchBrowser, path: string, newFileName: stri } contextMenuClick(document.querySelector('[data-path="' + path + '"]')) }, [path], function () { - browser - .click('#menuitemrename') - .sendKeys('[data-input-path="' + path + '"]', newFileName) - .sendKeys('[data-input-path="' + path + '"]', browser.Keys.ENTER) - .waitForElementNotPresent('[data-path="' + path + '"]') - .waitForElementPresent('[data-path="' + renamedPath + '"]') - .perform(() => { - done() - }) + try { + browser + .click('#menuitemrename') + .sendKeys('[data-input-path="' + path + '"]', newFileName) + .sendKeys('[data-input-path="' + path + '"]', browser.Keys.ENTER) + .waitForElementNotPresent('[data-path="' + path + '"]') + .waitForElementPresent('[data-path="' + renamedPath + '"]'); + } catch (error) { + console.error('An error occurred:', error.message); + // Handle error (e.g., take a screenshot, log the error, etc.) + } finally { + done(); // Ensure done is called even if there's an error + } }) } diff --git a/apps/remix-ide-e2e/src/tests/remixd.test.ts b/apps/remix-ide-e2e/src/tests/remixd.test.ts index 994d44d18f..b6be54cb5f 100644 --- a/apps/remix-ide-e2e/src/tests/remixd.test.ts +++ b/apps/remix-ide-e2e/src/tests/remixd.test.ts @@ -51,6 +51,36 @@ const sources = [ } ] +function isPortInUse(port) { + return new Promise((resolve, reject) => { + const lsof = spawn('lsof', ['-i', `:${port}`]); + + let output = ''; + let error = ''; + + lsof.stdout.on('data', (data) => { + output += data.toString(); + }); + + lsof.stderr.on('data', (data) => { + error += data.toString(); + }); + + lsof.on('close', (code) => { + if (code === 0 && output) { + // Port is in use if lsof has output + resolve(true); + } else if (error) { + // Handle potential errors (e.g., lsof command not found) + reject(new Error(`lsof error: ${error}`)); + } else { + // Port is not in use + resolve(false); + } + }); + }); +} + module.exports = { '@disabled': true, before: function (browser, done) { @@ -59,15 +89,17 @@ module.exports = { after: function (browser) { browser.perform((done) => { - try { - console.log('remixd pid', remixd.pid); - treeKill(remixd.pid, 'SIGKILL', (err) => { - console.log('remixd killed', err) - }) - console.log('Service disconnected successfully.'); - } catch (error) { - console.error('Failed to disconnect service:', error); - } + isPortInUse(65520).then((inUse) => { + try { + console.log('remixd pid', remixd.pid); + treeKill(remixd.pid, 'SIGKILL', (err) => { + console.log('remixd killed', err) + }) + console.log('Service disconnected successfully.'); + } catch (error) { + console.error('Failed to disconnect service:', error); + } + }) done() }) }, @@ -334,7 +366,7 @@ function runTests(browser: NightwatchBrowser, done: any) { .waitForElementVisible('[data-path="folder1"]') .waitForElementVisible('[data-path="folder1/contract_' + browserName + '.sol"]') .click('[data-path="folder1/contract_' + browserName + '.sol"]') // rename a file and check - .pause(1000) + .pause() .saveScreenshot('./reports/screenshots/remixd1.png') .renamePath('folder1/contract_' + browserName + '.sol', 'renamed_contract_' + browserName, 'folder1/renamed_contract_' + browserName + '.sol') .pause(1000) From 96b37d405ac6055ba07e5373056f96a1253780ef Mon Sep 17 00:00:00 2001 From: bunsenstraat Date: Wed, 21 Aug 2024 18:15:07 +0200 Subject: [PATCH 13/67] rm pause --- apps/remix-ide-e2e/src/commands/renamePath.ts | 1 - apps/remix-ide-e2e/src/tests/remixd.test.ts | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/remix-ide-e2e/src/commands/renamePath.ts b/apps/remix-ide-e2e/src/commands/renamePath.ts index 7ac7606631..e87df0cb95 100644 --- a/apps/remix-ide-e2e/src/commands/renamePath.ts +++ b/apps/remix-ide-e2e/src/commands/renamePath.ts @@ -41,7 +41,6 @@ function renamePath(browser: NightwatchBrowser, path: string, newFileName: strin .waitForElementPresent('[data-path="' + renamedPath + '"]'); } catch (error) { console.error('An error occurred:', error.message); - // Handle error (e.g., take a screenshot, log the error, etc.) } finally { done(); // Ensure done is called even if there's an error } diff --git a/apps/remix-ide-e2e/src/tests/remixd.test.ts b/apps/remix-ide-e2e/src/tests/remixd.test.ts index b6be54cb5f..78e98a1eef 100644 --- a/apps/remix-ide-e2e/src/tests/remixd.test.ts +++ b/apps/remix-ide-e2e/src/tests/remixd.test.ts @@ -366,7 +366,7 @@ function runTests(browser: NightwatchBrowser, done: any) { .waitForElementVisible('[data-path="folder1"]') .waitForElementVisible('[data-path="folder1/contract_' + browserName + '.sol"]') .click('[data-path="folder1/contract_' + browserName + '.sol"]') // rename a file and check - .pause() + .pause(1000) .saveScreenshot('./reports/screenshots/remixd1.png') .renamePath('folder1/contract_' + browserName + '.sol', 'renamed_contract_' + browserName, 'folder1/renamed_contract_' + browserName + '.sol') .pause(1000) From ae073ecdffc1c9f9d4cfeb3044859d7d063718d9 Mon Sep 17 00:00:00 2001 From: bunsenstraat Date: Wed, 21 Aug 2024 18:16:33 +0200 Subject: [PATCH 14/67] rm screenshot --- apps/remix-ide-e2e/src/tests/remixd.test.ts | 50 +++++---------------- 1 file changed, 10 insertions(+), 40 deletions(-) diff --git a/apps/remix-ide-e2e/src/tests/remixd.test.ts b/apps/remix-ide-e2e/src/tests/remixd.test.ts index 78e98a1eef..1b71322931 100644 --- a/apps/remix-ide-e2e/src/tests/remixd.test.ts +++ b/apps/remix-ide-e2e/src/tests/remixd.test.ts @@ -51,35 +51,7 @@ const sources = [ } ] -function isPortInUse(port) { - return new Promise((resolve, reject) => { - const lsof = spawn('lsof', ['-i', `:${port}`]); - - let output = ''; - let error = ''; - lsof.stdout.on('data', (data) => { - output += data.toString(); - }); - - lsof.stderr.on('data', (data) => { - error += data.toString(); - }); - - lsof.on('close', (code) => { - if (code === 0 && output) { - // Port is in use if lsof has output - resolve(true); - } else if (error) { - // Handle potential errors (e.g., lsof command not found) - reject(new Error(`lsof error: ${error}`)); - } else { - // Port is not in use - resolve(false); - } - }); - }); -} module.exports = { '@disabled': true, @@ -89,17 +61,15 @@ module.exports = { after: function (browser) { browser.perform((done) => { - isPortInUse(65520).then((inUse) => { - try { - console.log('remixd pid', remixd.pid); - treeKill(remixd.pid, 'SIGKILL', (err) => { - console.log('remixd killed', err) - }) - console.log('Service disconnected successfully.'); - } catch (error) { - console.error('Failed to disconnect service:', error); - } - }) + try { + console.log('remixd pid', remixd.pid); + treeKill(remixd.pid, 'SIGKILL', (err) => { + console.log('remixd killed', err) + }) + console.log('Service disconnected successfully.'); + } catch (error) { + console.error('Failed to disconnect service:', error); + } done() }) }, @@ -367,7 +337,7 @@ function runTests(browser: NightwatchBrowser, done: any) { .waitForElementVisible('[data-path="folder1/contract_' + browserName + '.sol"]') .click('[data-path="folder1/contract_' + browserName + '.sol"]') // rename a file and check .pause(1000) - .saveScreenshot('./reports/screenshots/remixd1.png') + .renamePath('folder1/contract_' + browserName + '.sol', 'renamed_contract_' + browserName, 'folder1/renamed_contract_' + browserName + '.sol') .pause(1000) .removeFile('folder1/contract_' + browserName + '_toremove.sol', 'localhost') From f7b22c4c6435843a30e40bad52bc00046b01fbc3 Mon Sep 17 00:00:00 2001 From: bunsenstraat Date: Wed, 21 Aug 2024 18:50:49 +0200 Subject: [PATCH 15/67] reset head --- apps/remix-ide-e2e/src/tests/ballot.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/remix-ide-e2e/src/tests/ballot.test.ts b/apps/remix-ide-e2e/src/tests/ballot.test.ts index d97a362ea3..c9fb7c27bc 100644 --- a/apps/remix-ide-e2e/src/tests/ballot.test.ts +++ b/apps/remix-ide-e2e/src/tests/ballot.test.ts @@ -23,7 +23,7 @@ module.exports = { 'Deploy Ballot #group1': function (browser: NightwatchBrowser) { browser .waitForElementVisible('*[data-id="remixIdeIconPanel"]', 10000) - .clickLaunchIcon('solidity2') + .clickLaunchIcon('solidity') .testContracts('Untitled.sol', sources[0]['Untitled.sol'], ['Ballot']) .clickLaunchIcon('udapp') .selectAccount('0xCA35b7d915458EF540aDe6068dFe2F44E8fa733c') From 697bbf9af652a2935034cd5653272e183111dc64 Mon Sep 17 00:00:00 2001 From: bunsenstraat Date: Wed, 21 Aug 2024 18:50:55 +0200 Subject: [PATCH 16/67] reset head --- apps/remix-ide-e2e/src/tests/remixd.test.ts | 33 +++++++++++++++++++-- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/apps/remix-ide-e2e/src/tests/remixd.test.ts b/apps/remix-ide-e2e/src/tests/remixd.test.ts index 1b71322931..6cc9018710 100644 --- a/apps/remix-ide-e2e/src/tests/remixd.test.ts +++ b/apps/remix-ide-e2e/src/tests/remixd.test.ts @@ -2,10 +2,9 @@ import { NightwatchBrowser } from 'nightwatch' import init from '../helpers/init' import { join } from 'path' -import { ChildProcess, spawn } from 'child_process' +import { ChildProcess, exec, spawn } from 'child_process' import { homedir } from 'os' - -import kill from 'tree-kill' +import fs from 'fs' import treeKill from 'tree-kill' let remixd: ChildProcess @@ -70,6 +69,11 @@ module.exports = { } catch (error) { console.error('Failed to disconnect service:', error); } + try { + resetGitToHead() + } catch (error) { + console.error('Failed to restore git changes:', error); + } done() }) }, @@ -593,3 +597,26 @@ async function installSlither(): Promise { console.log(e) } } + + +function resetGitToHead() { + if (process.env.CIRCLECI) { + console.log("Running on CircleCI, resetting Git to HEAD..."); + } else { + console.log("Not running on CircleCI, skipping Git reset."); + return + } + const command = 'git reset --hard HEAD && git clean -fd'; + + exec(command, (error, stdout, stderr) => { + if (error) { + console.error(`Error executing command: ${command}\n${error.message}`); + return; + } + if (stderr) { + console.error(`Error output from command: ${command}\n${stderr}`); + return; + } + console.log(`Git reset to HEAD successfully.\n${stdout}`); + }); +} \ No newline at end of file From 4f4c16c12c120b172d9d00e6f739b5c9721b7293 Mon Sep 17 00:00:00 2001 From: bunsenstraat Date: Wed, 21 Aug 2024 19:10:49 +0200 Subject: [PATCH 17/67] end session --- apps/remix-ide-e2e/src/tests/remixd.test.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/remix-ide-e2e/src/tests/remixd.test.ts b/apps/remix-ide-e2e/src/tests/remixd.test.ts index 6cc9018710..8b327af6f3 100644 --- a/apps/remix-ide-e2e/src/tests/remixd.test.ts +++ b/apps/remix-ide-e2e/src/tests/remixd.test.ts @@ -87,6 +87,8 @@ module.exports = { remixd = await spawnRemixd(join(process.cwd(), '/apps/remix-ide', '/contracts')) } catch (err) { console.error(err) + // end the session + browser.end() } console.log('working directory', process.cwd()) connectRemixd(browser, done) From afb552ff9a39d544a56998f51792db3cf395e0fa Mon Sep 17 00:00:00 2001 From: bunsenstraat Date: Wed, 21 Aug 2024 19:30:09 +0200 Subject: [PATCH 18/67] add fails --- apps/remix-ide-e2e/src/tests/remixd.test.ts | 37 +++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/apps/remix-ide-e2e/src/tests/remixd.test.ts b/apps/remix-ide-e2e/src/tests/remixd.test.ts index 8b327af6f3..addbfa9294 100644 --- a/apps/remix-ide-e2e/src/tests/remixd.test.ts +++ b/apps/remix-ide-e2e/src/tests/remixd.test.ts @@ -4,7 +4,6 @@ import init from '../helpers/init' import { join } from 'path' import { ChildProcess, exec, spawn } from 'child_process' import { homedir } from 'os' -import fs from 'fs' import treeKill from 'tree-kill' let remixd: ChildProcess @@ -81,12 +80,14 @@ module.exports = { '@sources': function () { return sources }, - 'run Remixd tests #group1 #flaky': function (browser) { + 'run Remixd tests #group1 #flaky': function (browser: NightwatchBrowser) { browser.perform(async (done) => { try { remixd = await spawnRemixd(join(process.cwd(), '/apps/remix-ide', '/contracts')) } catch (err) { console.error(err) + // fail + browser.assert.fail('Failed to start remixd') // end the session browser.end() } @@ -103,7 +104,13 @@ module.exports = { remix try to resolve it against the node_modules and installed_contracts folder. */ browser.perform(async (done) => { + try{ remixd = await spawnRemixd(join(process.cwd(), '/apps/remix-ide', '/contracts')) + } catch (err) { + console.error(err) + browser.assert.fail('Failed to start remixd') + browser.end() + } console.log('working directory', process.cwd()) connectRemixd(browser, done) }) @@ -114,7 +121,13 @@ module.exports = { }, 'Import from node_modules and reference a github import #group3': function (browser) { browser.perform(async (done) => { + try{ remixd = await spawnRemixd(join(process.cwd(), '/apps/remix-ide', '/contracts')) + } catch (err) { + console.error(err) + browser.assert.fail('Failed to start remixd') + browser.end() + } console.log('working directory', process.cwd()) connectRemixd(browser, done) }) @@ -134,7 +147,13 @@ module.exports = { 'Should listen on compilation result from hardhat #group4': function (browser: NightwatchBrowser) { browser.perform(async (done) => { + try{ remixd = await spawnRemixd(join(process.cwd(), '/apps/remix-ide/hardhat-boilerplate')) + } catch (err) { + console.error(err) + browser.assert.fail('Failed to start remixd') + browser.end() + } console.log('working directory', process.cwd()) connectRemixd(browser, done) }) @@ -205,7 +224,13 @@ module.exports = { browser.perform(async (done) => { console.log('working directory', homedir() + '/foundry_tmp/hello_foundry') + try{ remixd = await spawnRemixd(join(homedir(), '/foundry_tmp/hello_foundry')) + } catch (err) { + console.error(err) + browser.assert.fail('Failed to start remixd') + browser.end() + } connectRemixd(browser, done) }) .perform(async (done) => { @@ -266,7 +291,13 @@ module.exports = { 'Should disable git when running remixd #group9': function (browser: NightwatchBrowser) { browser.perform(async (done) => { + try{ remixd = await spawnRemixd(join(process.cwd(), '/apps/remix-ide', '/contracts/hardhat')) + } catch (err) { + console.error(err) + browser.assert.fail('Failed to start remixd') + browser.end() + } console.log('working directory', process.cwd()) connectRemixd(browser, done) }) @@ -298,6 +329,8 @@ module.exports = { remixd = await spawnRemixd(join(process.cwd(), '/apps/remix-ide', '/contracts')) } catch (err) { console.error(err) + browser.assert.fail('Failed to start remixd') + browser.end() } console.log('working directory', process.cwd()) connectRemixd(browser, done) From 4df544954422f4303a08e8c9ea62c24dd707cf11 Mon Sep 17 00:00:00 2001 From: bunsenstraat Date: Wed, 21 Aug 2024 19:31:39 +0200 Subject: [PATCH 19/67] fail --- apps/remix-ide-e2e/src/tests/remixd.test.ts | 8 -------- 1 file changed, 8 deletions(-) diff --git a/apps/remix-ide-e2e/src/tests/remixd.test.ts b/apps/remix-ide-e2e/src/tests/remixd.test.ts index addbfa9294..7bd1036781 100644 --- a/apps/remix-ide-e2e/src/tests/remixd.test.ts +++ b/apps/remix-ide-e2e/src/tests/remixd.test.ts @@ -88,8 +88,6 @@ module.exports = { console.error(err) // fail browser.assert.fail('Failed to start remixd') - // end the session - browser.end() } console.log('working directory', process.cwd()) connectRemixd(browser, done) @@ -109,7 +107,6 @@ module.exports = { } catch (err) { console.error(err) browser.assert.fail('Failed to start remixd') - browser.end() } console.log('working directory', process.cwd()) connectRemixd(browser, done) @@ -126,7 +123,6 @@ module.exports = { } catch (err) { console.error(err) browser.assert.fail('Failed to start remixd') - browser.end() } console.log('working directory', process.cwd()) connectRemixd(browser, done) @@ -152,7 +148,6 @@ module.exports = { } catch (err) { console.error(err) browser.assert.fail('Failed to start remixd') - browser.end() } console.log('working directory', process.cwd()) connectRemixd(browser, done) @@ -229,7 +224,6 @@ module.exports = { } catch (err) { console.error(err) browser.assert.fail('Failed to start remixd') - browser.end() } connectRemixd(browser, done) }) @@ -296,7 +290,6 @@ module.exports = { } catch (err) { console.error(err) browser.assert.fail('Failed to start remixd') - browser.end() } console.log('working directory', process.cwd()) connectRemixd(browser, done) @@ -330,7 +323,6 @@ module.exports = { } catch (err) { console.error(err) browser.assert.fail('Failed to start remixd') - browser.end() } console.log('working directory', process.cwd()) connectRemixd(browser, done) From bee420d8907951e9ab2c1a8ee734fbeb71cda7ea Mon Sep 17 00:00:00 2001 From: bunsenstraat Date: Wed, 21 Aug 2024 19:32:20 +0200 Subject: [PATCH 20/67] rm fn --- apps/remix-ide-e2e/src/tests/remixd.test.ts | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/apps/remix-ide-e2e/src/tests/remixd.test.ts b/apps/remix-ide-e2e/src/tests/remixd.test.ts index 7bd1036781..12740b413d 100644 --- a/apps/remix-ide-e2e/src/tests/remixd.test.ts +++ b/apps/remix-ide-e2e/src/tests/remixd.test.ts @@ -440,27 +440,6 @@ async function spawnRemixd(path: string): Promise { }) } -function killProcess(pid, signal = 'SIGKILL') { - return new Promise((resolve, reject) => { - const kill = spawn('kill', ['-s', signal, pid]); - - kill.on('close', (code) => { - if (code === 0) { - console.log(`Successfully killed process with PID: ${pid}`); - resolve(); - } else { - console.error(`Failed to kill process with PID: ${pid}. Exit code: ${code}`); - reject(new Error(`kill process failed with code ${code}`)); - } - }); - - kill.on('error', (err) => { - console.error(`Error spawning kill process: ${err.message}`); - reject(err); - }); - }); -} - function connectRemixd(browser: NightwatchBrowser, done: any) { const browserName = browser.options.desiredCapabilities.browserName if (browserName === 'safari' || browserName === 'internet explorer') { From 1a2b0c747e120d3452ced1a71b580ec8cd900519 Mon Sep 17 00:00:00 2001 From: bunsenstraat Date: Wed, 21 Aug 2024 20:23:09 +0200 Subject: [PATCH 21/67] undo flaky --- .circleci/config.yml | 2 +- apps/remix-ide-e2e/src/tests/remixd.test.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index a95ed97b6b..d5a065c41d 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -3,7 +3,7 @@ version: 2.1 parameters: run_flaky_tests: type: boolean - default: true + default: false orbs: browser-tools: circleci/browser-tools@1.4.4 win: circleci/windows@5.0 diff --git a/apps/remix-ide-e2e/src/tests/remixd.test.ts b/apps/remix-ide-e2e/src/tests/remixd.test.ts index 12740b413d..31dc3c686b 100644 --- a/apps/remix-ide-e2e/src/tests/remixd.test.ts +++ b/apps/remix-ide-e2e/src/tests/remixd.test.ts @@ -80,7 +80,7 @@ module.exports = { '@sources': function () { return sources }, - 'run Remixd tests #group1 #flaky': function (browser: NightwatchBrowser) { + 'run Remixd tests #group1': function (browser: NightwatchBrowser) { browser.perform(async (done) => { try { remixd = await spawnRemixd(join(process.cwd(), '/apps/remix-ide', '/contracts')) From 2061210ee83c8bb961041aa1cebc83700e7489c3 Mon Sep 17 00:00:00 2001 From: bunsenstraat Date: Wed, 21 Aug 2024 20:23:40 +0200 Subject: [PATCH 22/67] restore flaky --- apps/remix-ide/ci/flaky.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/remix-ide/ci/flaky.sh b/apps/remix-ide/ci/flaky.sh index 69c7bbe734..5373daec0b 100755 --- a/apps/remix-ide/ci/flaky.sh +++ b/apps/remix-ide/ci/flaky.sh @@ -23,7 +23,7 @@ yarn run serve:production & sleep 5 for TESTFILE in $TESTFILES; do - npx nightwatch --config dist/apps/remix-ide-e2e/nightwatch-${1}.js $TESTFILE --env=$1 || npx nightwatch --config dist/apps/remix-ide-e2e/nightwatch-${1}.js $TESTFILE --env=$1 || TEST_EXITCODE=1 + npx nightwatch --config dist/apps/remix-ide-e2e/nightwatch-${1}.js $TESTFILE --env=$1 || TEST_EXITCODE=1 done echo "$TEST_EXITCODE" From 18ccd758c5e716968b9cd13c1cfabefb7f824741 Mon Sep 17 00:00:00 2001 From: yann300 Date: Wed, 14 Aug 2024 14:56:15 +0200 Subject: [PATCH 23/67] persist providers --- apps/remix-ide-e2e/src/commands/pinGrid.ts | 19 ++++++++--- .../src/commands/switchEnvironment.ts | 34 +++++++++++++++---- apps/remix-ide-e2e/src/tests/grid.test.ts | 20 +++++++++++ apps/remix-ide-e2e/src/tests/plugin_api.ts | 8 +++++ apps/remix-ide/src/blockchain/blockchain.tsx | 18 +++++++++- .../src/lib/components/environment.tsx | 2 +- libs/remix-ui/tabs/src/lib/remix-ui-tabs.tsx | 2 +- 7 files changed, 89 insertions(+), 14 deletions(-) diff --git a/apps/remix-ide-e2e/src/commands/pinGrid.ts b/apps/remix-ide-e2e/src/commands/pinGrid.ts index 6c82922960..fb902006a9 100644 --- a/apps/remix-ide-e2e/src/commands/pinGrid.ts +++ b/apps/remix-ide-e2e/src/commands/pinGrid.ts @@ -3,11 +3,20 @@ import EventEmitter from 'events' class pinGrid extends EventEmitter { command (this: NightwatchBrowser, provider: string, status: boolean): NightwatchBrowser { - this.api.useCss().waitForElementVisible('[data-id="settingsSelectEnvOptions"]') - .click('[data-id="settingsSelectEnvOptions"] button') - .waitForElementVisible(`[data-id="dropdown-item-another-chain"]`) - .click(`[data-id="dropdown-item-another-chain"]`) - .waitForElementVisible(`[data-id="${provider}-${status ? 'unpinned' : 'pinned'}"]`) + this.api.useCss() + .perform((done) => { + // check if the providers plugin is loaded. + this.api.isVisible({ selector: '[data-id="remixUIGSDeploy using a Browser Extension."]', suppressNotFoundErrors: true}, (result) => { + if (!result.value) { + this.api.waitForElementVisible('[data-id="settingsSelectEnvOptions"]') + .click('[data-id="settingsSelectEnvOptions"] button') + .waitForElementVisible(`[data-id="dropdown-item-another-chain"]`) + .click(`[data-id="dropdown-item-another-chain"]`) + .perform(() => done()) + } else done() + }) + }) + .waitForElementVisible(`[data-id="${provider}-${status ? 'unpinned' : 'pinned'}"]`, 60000) .click(`[data-id="${provider}-${status ? 'unpinned' : 'pinned'}"]`) .perform((done) => { done() diff --git a/apps/remix-ide-e2e/src/commands/switchEnvironment.ts b/apps/remix-ide-e2e/src/commands/switchEnvironment.ts index a2fc655cac..bd58e3121c 100644 --- a/apps/remix-ide-e2e/src/commands/switchEnvironment.ts +++ b/apps/remix-ide-e2e/src/commands/switchEnvironment.ts @@ -4,13 +4,35 @@ import EventEmitter from 'events' class switchEnvironment extends EventEmitter { command (this: NightwatchBrowser, provider: string): NightwatchBrowser { this.api.useCss().waitForElementVisible('[data-id="settingsSelectEnvOptions"]') - .click('[data-id="settingsSelectEnvOptions"] button') - .waitForElementVisible(`[data-id="dropdown-item-${provider}"]`) - .click(`[data-id="dropdown-item-${provider}"]`) .perform((done) => { - done() - this.emit('complete') - }) + this.api.isPresent({ selector: `[data-id="selected-provider-${provider}"]`, suppressNotFoundErrors: true, timeout: 5000}, (result) => { + if (result.value) { + done() + } else { + browser.perform(() => { + this.api + .click('[data-id="settingsSelectEnvOptions"] button') // open dropdown + .isPresent({ selector: `[data-id="dropdown-item-${provider}"]`, suppressNotFoundErrors: true, timeout: 5000}, (result) => { + console.log(result) + this.api.click('[data-id="settingsSelectEnvOptions"] button') // close dropdown + if (!result.value) { + this.api.pinGrid(provider, true) + .click('[data-id="settingsSelectEnvOptions"] button') + .waitForElementVisible(`[data-id="dropdown-item-${provider}"]`) + .click(`[data-id="dropdown-item-${provider}"]`) + .perform(() => done()) + } else { + browser.click('[data-id="settingsSelectEnvOptions"] button') + .waitForElementVisible(`[data-id="dropdown-item-${provider}"]`) + .click(`[data-id="dropdown-item-${provider}"]`) + .perform(() => done()) + } + }) + }) + } + }) + }).perform(() => this.emit('complete')) + return this } } diff --git a/apps/remix-ide-e2e/src/tests/grid.test.ts b/apps/remix-ide-e2e/src/tests/grid.test.ts index 5da7379328..73713d0dcd 100644 --- a/apps/remix-ide-e2e/src/tests/grid.test.ts +++ b/apps/remix-ide-e2e/src/tests/grid.test.ts @@ -32,5 +32,25 @@ module.exports = { .click('[data-id="settingsSelectEnvOptions"] button') .waitForElementNotPresent(`[data-id="dropdown-item-vm-sepolia-fork"]`) .click('[data-id="settingsSelectEnvOptions"] button') // close the dropdown + }, + 'remember pin upon reload': function (browser: NightwatchBrowser) { + browser + .pinGrid('vm-paris', true) + .click('[data-id="settingsSelectEnvOptions"] button') // open the dropdown + .waitForElementPresent(`[data-id="dropdown-item-vm-paris"]`) + .refreshPage() + .waitForElementVisible('[data-id="treeViewLitreeViewItemcontracts"]') // wait loaded + .clickLaunchIcon('udapp') + .click('[data-id="settingsSelectEnvOptions"] button') // open the dropdown + .waitForElementPresent(`[data-id="dropdown-item-vm-paris"]`) + .click('[data-id="settingsSelectEnvOptions"] button') // close the dropdown + .pinGrid('vm-paris', false) + .click('[data-id="settingsSelectEnvOptions"] button') // open the dropdown + .waitForElementNotPresent(`[data-id="dropdown-item-vm-paris"]`) + .refreshPage() + .waitForElementVisible('[data-id="treeViewLitreeViewItemcontracts"]') // wait loaded + .clickLaunchIcon('udapp') + .click('[data-id="settingsSelectEnvOptions"] button') // open the dropdown + .waitForElementNotPresent(`[data-id="dropdown-item-vm-paris"]`) } } \ No newline at end of file diff --git a/apps/remix-ide-e2e/src/tests/plugin_api.ts b/apps/remix-ide-e2e/src/tests/plugin_api.ts index b42f082b3e..801e7c4e6d 100644 --- a/apps/remix-ide-e2e/src/tests/plugin_api.ts +++ b/apps/remix-ide-e2e/src/tests/plugin_api.ts @@ -179,6 +179,14 @@ module.exports = { }, 'Should select another provider #group1': async function (browser: NightwatchBrowser) { + await browser + .frameParent() + .useCss() + .clickLaunchIcon('udapp') + .pinGrid('vm-berlin', true) + .clickLaunchIcon('localPlugin') + .useXpath() + .frame(0) await clickAndCheckLog(browser, 'udapp:setEnvironmentMode', null, null, { context: 'vm-berlin' }) await browser .frameParent() diff --git a/apps/remix-ide/src/blockchain/blockchain.tsx b/apps/remix-ide/src/blockchain/blockchain.tsx index 00a64273f0..66f3baafc1 100644 --- a/apps/remix-ide/src/blockchain/blockchain.tsx +++ b/apps/remix-ide/src/blockchain/blockchain.tsx @@ -80,6 +80,7 @@ export class Blockchain extends Plugin { providers: {[key: string]: VMProvider | InjectedProvider | NodeProvider} transactionContextAPI: TransactionContextAPI registeredPluginEvents: string[] + defaultPinnedProviders: string[] pinnedProviders: string[] // NOTE: the config object will need to be refactored out in remix-lib @@ -112,7 +113,8 @@ export class Blockchain extends Plugin { this.networkcallid = 0 this.networkStatus = { network: { name: ' - ', id: ' - ' } } this.registeredPluginEvents = [] - this.pinnedProviders = ['vm-cancun', 'vm-shanghai', 'vm-mainnet-fork', 'vm-london', 'vm-berlin', 'vm-paris', 'walletconnect', 'injected-MetaMask', 'basic-http-provider', 'ganache-provider', 'hardhat-provider', 'foundry-provider'] + this.defaultPinnedProviders = ['vm-cancun', 'vm-mainnet-fork', 'walletconnect', 'injected-MetaMask', 'basic-http-provider', 'hardhat-provider', 'foundry-provider'] + this.pinnedProviders = [] this.setupEvents() this.setupProviders() } @@ -139,11 +141,25 @@ export class Blockchain extends Plugin { this.on('environmentExplorer', 'providerPinned', (name, provider) => { this.emit('shouldAddProvidertoUdapp', name, provider) + this.pinnedProviders.push(name) + this.call('config', 'setAppParameter', 'settings/pinned-providers', JSON.stringify(this.pinnedProviders)) }) this.on('environmentExplorer', 'providerUnpinned', (name, provider) => { this.emit('shouldRemoveProviderFromUdapp', name, provider) + const index = this.pinnedProviders.indexOf(name) + this.pinnedProviders.splice(index, 1) + this.call('config', 'setAppParameter', 'settings/pinned-providers', JSON.stringify(this.pinnedProviders)) }) + + this.call('config', 'getAppParameter', 'settings/pinned-providers').then((providers) => { + if (!providers) { + this.call('config', 'setAppParameter', 'settings/pinned-providers', JSON.stringify(this.defaultPinnedProviders)) + this.pinnedProviders = this.defaultPinnedProviders + } else { + this.pinnedProviders = JSON.parse(providers) + } + }).catch((error) => { console.log(error) }) } onDeactivation() { diff --git a/libs/remix-ui/run-tab/src/lib/components/environment.tsx b/libs/remix-ui/run-tab/src/lib/components/environment.tsx index 95fbf0afa4..d499b9c917 100644 --- a/libs/remix-ui/run-tab/src/lib/components/environment.tsx +++ b/libs/remix-ui/run-tab/src/lib/components/environment.tsx @@ -39,7 +39,7 @@ export function EnvironmentUI(props: EnvironmentProps) { -
+
{isL2(currentProvider && currentProvider.displayName)} diff --git a/libs/remix-ui/tabs/src/lib/remix-ui-tabs.tsx b/libs/remix-ui/tabs/src/lib/remix-ui-tabs.tsx index f5c3a668c0..311b4c166a 100644 --- a/libs/remix-ui/tabs/src/lib/remix-ui-tabs.tsx +++ b/libs/remix-ui/tabs/src/lib/remix-ui-tabs.tsx @@ -320,7 +320,7 @@ export const TabsUI = (props: TabsUIProps) => { > {props.tabs.map((tab, i) => ( - + {renderTab(tab, i)} ))} From 9a8e4d70aaec04788835526109da06bcada32f81 Mon Sep 17 00:00:00 2001 From: bunsenstraat Date: Thu, 22 Aug 2024 08:50:37 +0200 Subject: [PATCH 24/67] set flaky test --- .circleci/config.yml | 2 +- apps/remix-ide-e2e/src/tests/dgit_local.test.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index d5a065c41d..a95ed97b6b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -3,7 +3,7 @@ version: 2.1 parameters: run_flaky_tests: type: boolean - default: false + default: true orbs: browser-tools: circleci/browser-tools@1.4.4 win: circleci/windows@5.0 diff --git a/apps/remix-ide-e2e/src/tests/dgit_local.test.ts b/apps/remix-ide-e2e/src/tests/dgit_local.test.ts index fc0ec93f98..d6fabe17d8 100644 --- a/apps/remix-ide-e2e/src/tests/dgit_local.test.ts +++ b/apps/remix-ide-e2e/src/tests/dgit_local.test.ts @@ -238,7 +238,7 @@ module.exports = { .waitForElementVisible('*[data-id="branches-current-branch-testbranch"]') .pause(1000) }, - 'check if the branch is in the filePanel #group2': function (browser: NightwatchBrowser) { + 'check if the branch is in the filePanel #flaky #group2': function (browser: NightwatchBrowser) { browser .clickLaunchIcon('filePanel') .click('[data-id="workspaceGitBranchesDropdown"]') From 441c98138c57ea43a788294c8addba95e673bbde Mon Sep 17 00:00:00 2001 From: bunsenstraat Date: Thu, 22 Aug 2024 09:10:43 +0200 Subject: [PATCH 25/67] save screenshots --- apps/remix-ide-e2e/src/tests/dgit_local.test.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/remix-ide-e2e/src/tests/dgit_local.test.ts b/apps/remix-ide-e2e/src/tests/dgit_local.test.ts index d6fabe17d8..105f6ea961 100644 --- a/apps/remix-ide-e2e/src/tests/dgit_local.test.ts +++ b/apps/remix-ide-e2e/src/tests/dgit_local.test.ts @@ -241,7 +241,10 @@ module.exports = { 'check if the branch is in the filePanel #flaky #group2': function (browser: NightwatchBrowser) { browser .clickLaunchIcon('filePanel') + .saveScreenshot('./reports/screenshots/dgit_local.test.png') + .waitForElementVisible('*[data-id="workspaceGitBranchesDropdown"]') .click('[data-id="workspaceGitBranchesDropdown"]') + .saveScreenshot('./reports/screenshots/dgit_local_2.test.png') .expect.element('[data-id="workspaceGit-testbranch"]').text.to.contain('✓ ') }, 'publish the branch #group2': function (browser: NightwatchBrowser) { From 4f6251fdb6c7fc9454c86417350a6a9f033ab800 Mon Sep 17 00:00:00 2001 From: bunsenstraat Date: Thu, 22 Aug 2024 09:35:48 +0200 Subject: [PATCH 26/67] wait for element --- apps/remix-ide-e2e/src/tests/dgit_local.test.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/remix-ide-e2e/src/tests/dgit_local.test.ts b/apps/remix-ide-e2e/src/tests/dgit_local.test.ts index 105f6ea961..7cc791228d 100644 --- a/apps/remix-ide-e2e/src/tests/dgit_local.test.ts +++ b/apps/remix-ide-e2e/src/tests/dgit_local.test.ts @@ -317,6 +317,10 @@ module.exports = { }, 'switch back to master #group2': function (browser: NightwatchBrowser) { browser + .waitForElementVisible({ + selector: "//*[@data-id='branches-panel-content']//*[@data-id='branches-toggle-branch-master']", + locateStrategy: 'xpath', + }) .click({ selector: "//*[@data-id='branches-panel-content']//*[@data-id='branches-toggle-branch-master']", locateStrategy: 'xpath', From ab218260087e800eee50632f7007540633d47b07 Mon Sep 17 00:00:00 2001 From: bunsenstraat Date: Thu, 22 Aug 2024 09:45:58 +0200 Subject: [PATCH 27/67] timeout --- apps/remix-ide-e2e/src/tests/dgit_local.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/remix-ide-e2e/src/tests/dgit_local.test.ts b/apps/remix-ide-e2e/src/tests/dgit_local.test.ts index 7cc791228d..27c30a5275 100644 --- a/apps/remix-ide-e2e/src/tests/dgit_local.test.ts +++ b/apps/remix-ide-e2e/src/tests/dgit_local.test.ts @@ -328,6 +328,7 @@ module.exports = { .waitForElementVisible({ selector: "//*[@data-id='branches-panel-content']//*[@data-id='branches-toggle-current-branch-master']", locateStrategy: 'xpath', + timeout: 60000 }) }, 'check if test file is gone #group2': function (browser: NightwatchBrowser) { From bf5982e979e3a3acad636f08680764353ef08e1b Mon Sep 17 00:00:00 2001 From: bunsenstraat Date: Thu, 22 Aug 2024 10:05:10 +0200 Subject: [PATCH 28/67] rm screens --- apps/remix-ide-e2e/src/tests/dgit_local.test.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/apps/remix-ide-e2e/src/tests/dgit_local.test.ts b/apps/remix-ide-e2e/src/tests/dgit_local.test.ts index 27c30a5275..984d17113f 100644 --- a/apps/remix-ide-e2e/src/tests/dgit_local.test.ts +++ b/apps/remix-ide-e2e/src/tests/dgit_local.test.ts @@ -241,10 +241,8 @@ module.exports = { 'check if the branch is in the filePanel #flaky #group2': function (browser: NightwatchBrowser) { browser .clickLaunchIcon('filePanel') - .saveScreenshot('./reports/screenshots/dgit_local.test.png') .waitForElementVisible('*[data-id="workspaceGitBranchesDropdown"]') .click('[data-id="workspaceGitBranchesDropdown"]') - .saveScreenshot('./reports/screenshots/dgit_local_2.test.png') .expect.element('[data-id="workspaceGit-testbranch"]').text.to.contain('✓ ') }, 'publish the branch #group2': function (browser: NightwatchBrowser) { From cded07a83f7b38e2fba5a0479f0c7033b342e43b Mon Sep 17 00:00:00 2001 From: bunsenstraat Date: Thu, 22 Aug 2024 10:14:23 +0200 Subject: [PATCH 29/67] add a pause --- apps/remix-ide-e2e/src/tests/dgit_local.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/remix-ide-e2e/src/tests/dgit_local.test.ts b/apps/remix-ide-e2e/src/tests/dgit_local.test.ts index 984d17113f..5c51074217 100644 --- a/apps/remix-ide-e2e/src/tests/dgit_local.test.ts +++ b/apps/remix-ide-e2e/src/tests/dgit_local.test.ts @@ -242,6 +242,7 @@ module.exports = { browser .clickLaunchIcon('filePanel') .waitForElementVisible('*[data-id="workspaceGitBranchesDropdown"]') + .pause(1000) .click('[data-id="workspaceGitBranchesDropdown"]') .expect.element('[data-id="workspaceGit-testbranch"]').text.to.contain('✓ ') }, From d82978ed032521c0f2dfdba1f69a9aa7eaf13d4d Mon Sep 17 00:00:00 2001 From: bunsenstraat Date: Thu, 22 Aug 2024 10:24:53 +0200 Subject: [PATCH 30/67] run nx --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 7db9ea7eb2..ac30557b8c 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ "serve:hot": "nx serve remix-ide --configuration=hot", "serve:plugin": "nx serve ${npm_config_plugin} --configuration=development", "build:plugin": "NODE_ENV=production nx build ${npm_config_plugin} --configuration=production --skip-nx-cache", - "build": "nx build", + "build": "nx build --parallel --maxParallel=6", "test": "nx test", "lint": "nx lint", "affected:apps": "nx affected:apps", @@ -72,7 +72,7 @@ "downloadsolc_assets_e2e": "node ./apps/remix-ide/ci/download_e2e_assets.js", "make-mock-compiler": "node apps/remix-ide/ci/makeMockCompiler.js", "minify": "uglifyjs --in-source-map inline --source-map-inline -c warnings=false", - "build:production": "NODE_ENV=production nx build remix-ide --configuration=production --skip-nx-cache", + "build:production": "NODE_ENV=production nx build remix-ide --configuration=production --skip-nx-cache --parallel --maxParallel=6", "serve:production": "npx http-server ./dist/apps/remix-ide", "install_webdriver": "bash ./apps/remix-ide-e2e/install-webdriver.sh", "select_test": "bash apps/remix-ide-e2e/src/select_tests.sh", From 6ffcbc696b8371813c68251d8baecb505213cbe6 Mon Sep 17 00:00:00 2001 From: bunsenstraat Date: Thu, 22 Aug 2024 10:29:51 +0200 Subject: [PATCH 31/67] restore pack --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index ac30557b8c..7db9ea7eb2 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ "serve:hot": "nx serve remix-ide --configuration=hot", "serve:plugin": "nx serve ${npm_config_plugin} --configuration=development", "build:plugin": "NODE_ENV=production nx build ${npm_config_plugin} --configuration=production --skip-nx-cache", - "build": "nx build --parallel --maxParallel=6", + "build": "nx build", "test": "nx test", "lint": "nx lint", "affected:apps": "nx affected:apps", @@ -72,7 +72,7 @@ "downloadsolc_assets_e2e": "node ./apps/remix-ide/ci/download_e2e_assets.js", "make-mock-compiler": "node apps/remix-ide/ci/makeMockCompiler.js", "minify": "uglifyjs --in-source-map inline --source-map-inline -c warnings=false", - "build:production": "NODE_ENV=production nx build remix-ide --configuration=production --skip-nx-cache --parallel --maxParallel=6", + "build:production": "NODE_ENV=production nx build remix-ide --configuration=production --skip-nx-cache", "serve:production": "npx http-server ./dist/apps/remix-ide", "install_webdriver": "bash ./apps/remix-ide-e2e/install-webdriver.sh", "select_test": "bash apps/remix-ide-e2e/src/select_tests.sh", From f27c5a5cf4f8f1ad023bcbed634df786275d196e Mon Sep 17 00:00:00 2001 From: bunsenstraat Date: Thu, 22 Aug 2024 11:10:08 +0200 Subject: [PATCH 32/67] add extra click --- apps/remix-ide-e2e/src/tests/dgit_local.test.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/apps/remix-ide-e2e/src/tests/dgit_local.test.ts b/apps/remix-ide-e2e/src/tests/dgit_local.test.ts index 5c51074217..5d618638ac 100644 --- a/apps/remix-ide-e2e/src/tests/dgit_local.test.ts +++ b/apps/remix-ide-e2e/src/tests/dgit_local.test.ts @@ -324,6 +324,13 @@ module.exports = { selector: "//*[@data-id='branches-panel-content']//*[@data-id='branches-toggle-branch-master']", locateStrategy: 'xpath', }) + .pause(1000) + .click({ + selector: "//*[@data-id='branches-panel-content']//*[@data-id='branches-toggle-branch-master']", + locateStrategy: 'xpath', + abortOnFailure: false, + suppressNotFoundErrors: true + }) .waitForElementVisible({ selector: "//*[@data-id='branches-panel-content']//*[@data-id='branches-toggle-current-branch-master']", locateStrategy: 'xpath', @@ -332,7 +339,7 @@ module.exports = { }, 'check if test file is gone #group2': function (browser: NightwatchBrowser) { browser - .pause() + .pause(2000) .clickLaunchIcon('filePanel') .waitForElementNotPresent('*[data-id="treeViewLitreeViewItemtest.txt"]') }, From ac488b70ec13310fd467ff2cb663b5eae16b931c Mon Sep 17 00:00:00 2001 From: bunsenstraat Date: Thu, 22 Aug 2024 12:17:44 +0200 Subject: [PATCH 33/67] turn off flaky --- .circleci/config.yml | 2 +- apps/remix-ide-e2e/src/tests/dgit_local.test.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index a95ed97b6b..d5a065c41d 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -3,7 +3,7 @@ version: 2.1 parameters: run_flaky_tests: type: boolean - default: true + default: false orbs: browser-tools: circleci/browser-tools@1.4.4 win: circleci/windows@5.0 diff --git a/apps/remix-ide-e2e/src/tests/dgit_local.test.ts b/apps/remix-ide-e2e/src/tests/dgit_local.test.ts index 5d618638ac..b6ee642a27 100644 --- a/apps/remix-ide-e2e/src/tests/dgit_local.test.ts +++ b/apps/remix-ide-e2e/src/tests/dgit_local.test.ts @@ -238,7 +238,7 @@ module.exports = { .waitForElementVisible('*[data-id="branches-current-branch-testbranch"]') .pause(1000) }, - 'check if the branch is in the filePanel #flaky #group2': function (browser: NightwatchBrowser) { + 'check if the branch is in the filePanel #group2': function (browser: NightwatchBrowser) { browser .clickLaunchIcon('filePanel') .waitForElementVisible('*[data-id="workspaceGitBranchesDropdown"]') From 4b10b3e4bd269d8b79b2bf99f016c16376389634 Mon Sep 17 00:00:00 2001 From: bunsenstraat Date: Thu, 22 Aug 2024 12:26:26 +0200 Subject: [PATCH 34/67] optimize zip --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index d5a065c41d..ce6ee8f3bf 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -45,7 +45,7 @@ jobs: paths: - dist/apps/remix-ide/assets/js/soljson - - run: mkdir persist && zip -0 -r persist/dist.zip dist + - run: mkdir persist && zip -4 -r persist/dist.zip dist - persist_to_workspace: root: . paths: From b2b322c2b625319e4c632e210884d1a9d5f04983 Mon Sep 17 00:00:00 2001 From: bunsenstraat Date: Thu, 22 Aug 2024 12:33:59 +0200 Subject: [PATCH 35/67] zip increase --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index ce6ee8f3bf..d7c1a030c0 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -45,7 +45,7 @@ jobs: paths: - dist/apps/remix-ide/assets/js/soljson - - run: mkdir persist && zip -4 -r persist/dist.zip dist + - run: mkdir persist && zip -5 -r persist/dist.zip dist - persist_to_workspace: root: . paths: From 9a102dd68bc4fba0fd2960ecf94aeaa7c6df554d Mon Sep 17 00:00:00 2001 From: bunsenstraat Date: Thu, 22 Aug 2024 12:53:18 +0200 Subject: [PATCH 36/67] use zst --- .circleci/config.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index d7c1a030c0..d5e3a00d94 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -45,7 +45,7 @@ jobs: paths: - dist/apps/remix-ide/assets/js/soljson - - run: mkdir persist && zip -5 -r persist/dist.zip dist + - run: mkdir persist && tar -cf - dist | zstd -5 -o persist/dist.tar.zst - persist_to_workspace: root: . paths: @@ -360,7 +360,8 @@ jobs: - checkout - attach_workspace: at: . - - run: unzip ./persist/dist.zip + - run: zstd -d persist/dist.tar.zst -o persist/dist.tar + - run: tar -xf persist/dist.tar - run: yarn install --cwd ./apps/remix-ide-e2e --modules-folder ../../node_modules || yarn install --cwd ./apps/remix-ide-e2e --modules-folder ../../node_modules - run: mkdir node_modules/hardhat && wget https://unpkg.com/hardhat/console.sol -O node_modules/hardhat/console.sol - run: ls -la ./dist/apps/remix-ide/assets/js @@ -416,7 +417,8 @@ jobs: - checkout - attach_workspace: at: . - - run: unzip ./persist/dist.zip + - run: zstd -d persist/dist.tar.zst -o persist/dist.tar + - run: tar -xf persist/dist.tar - run: unzip ./persist/plugin-<< parameters.plugin >>.zip - run: yarn install --cwd ./apps/remix-ide-e2e --modules-folder ../../node_modules || yarn install --cwd ./apps/remix-ide-e2e --modules-folder ../../node_modules - browser-tools/install-browser-tools: From bde5886961f9b48dbb45533f8209fe3015a7aa25 Mon Sep 17 00:00:00 2001 From: bunsenstraat Date: Thu, 22 Aug 2024 12:57:46 +0200 Subject: [PATCH 37/67] install zstd --- .circleci/config.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index d5e3a00d94..b462a3969a 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -34,7 +34,7 @@ jobs: NX_BIN_URL=http://127.0.0.1:8080/assets/js/soljson NX_WASM_URL=http://127.0.0.1:8080/assets/js/soljson NX_NPM_URL=http://127.0.0.1:9090/ yarn build fi - run: yarn run build:e2e - + - run: sudo apt install zstd - run: grep -ir "[0-9]+commit" apps/* libs/* --include \*.ts --include \*.tsx --include \*.json > soljson-versions.txt - restore_cache: keys: @@ -44,7 +44,7 @@ jobs: key: soljson-v7-{{ checksum "soljson-versions.txt" }} paths: - dist/apps/remix-ide/assets/js/soljson - + - run: mkdir persist && tar -cf - dist | zstd -5 -o persist/dist.tar.zst - persist_to_workspace: root: . From 53b873feb1cac49f0bd36b047936a76c668f7533 Mon Sep 17 00:00:00 2001 From: bunsenstraat Date: Thu, 22 Aug 2024 13:00:50 +0200 Subject: [PATCH 38/67] install zstd --- .circleci/config.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index b462a3969a..83b22c12c1 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -16,6 +16,7 @@ jobs: xlarge working_directory: ~/remix-project steps: + - run: sudo apt update&& sudo apt install zstd - checkout - restore_cache: keys: @@ -34,7 +35,7 @@ jobs: NX_BIN_URL=http://127.0.0.1:8080/assets/js/soljson NX_WASM_URL=http://127.0.0.1:8080/assets/js/soljson NX_NPM_URL=http://127.0.0.1:9090/ yarn build fi - run: yarn run build:e2e - - run: sudo apt install zstd + - run: grep -ir "[0-9]+commit" apps/* libs/* --include \*.ts --include \*.tsx --include \*.json > soljson-versions.txt - restore_cache: keys: From 53a84a0edd577fc061e211a48951aca35a19daa6 Mon Sep 17 00:00:00 2001 From: bunsenstraat Date: Thu, 22 Aug 2024 13:07:01 +0200 Subject: [PATCH 39/67] install zstd --- .circleci/config.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 83b22c12c1..a91bc450ae 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -16,7 +16,7 @@ jobs: xlarge working_directory: ~/remix-project steps: - - run: sudo apt update&& sudo apt install zstd + - run: sudo apt update && sudo apt install zstd - checkout - restore_cache: keys: @@ -361,12 +361,13 @@ jobs: - checkout - attach_workspace: at: . + - run: sudo apt update && sudo apt install python3-pip -y zstd - run: zstd -d persist/dist.tar.zst -o persist/dist.tar - run: tar -xf persist/dist.tar - run: yarn install --cwd ./apps/remix-ide-e2e --modules-folder ../../node_modules || yarn install --cwd ./apps/remix-ide-e2e --modules-folder ../../node_modules - run: mkdir node_modules/hardhat && wget https://unpkg.com/hardhat/console.sol -O node_modules/hardhat/console.sol - run: ls -la ./dist/apps/remix-ide/assets/js - - run: sudo apt update && sudo apt install python3-pip -y + - when: condition: equal: [ "chrome", << parameters.browser >> ] From f7474d94fdb9851abe378a6d3e25775340ade0e3 Mon Sep 17 00:00:00 2001 From: bunsenstraat Date: Thu, 22 Aug 2024 13:14:49 +0200 Subject: [PATCH 40/67] 6 --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index a91bc450ae..f941165205 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -46,7 +46,7 @@ jobs: paths: - dist/apps/remix-ide/assets/js/soljson - - run: mkdir persist && tar -cf - dist | zstd -5 -o persist/dist.tar.zst + - run: mkdir persist && tar -cf - dist | zstd -6 -o persist/dist.tar.zst - persist_to_workspace: root: . paths: From 93fa561f8af4a65417b8f6d39fc2e73c3aba9e1f Mon Sep 17 00:00:00 2001 From: bunsenstraat Date: Thu, 22 Aug 2024 13:19:48 +0200 Subject: [PATCH 41/67] 3 --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index f941165205..1389718f30 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -46,7 +46,7 @@ jobs: paths: - dist/apps/remix-ide/assets/js/soljson - - run: mkdir persist && tar -cf - dist | zstd -6 -o persist/dist.tar.zst + - run: mkdir persist && tar -cf - dist | zstd -3 -o persist/dist.tar.zst - persist_to_workspace: root: . paths: From a6ad34592f9990c0bbf07586118a68624fcc18dc Mon Sep 17 00:00:00 2001 From: bunsenstraat Date: Thu, 22 Aug 2024 13:28:17 +0200 Subject: [PATCH 42/67] 1 --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 1389718f30..387ee29962 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -46,7 +46,7 @@ jobs: paths: - dist/apps/remix-ide/assets/js/soljson - - run: mkdir persist && tar -cf - dist | zstd -3 -o persist/dist.tar.zst + - run: mkdir persist && tar -cf - dist | zstd -1 -o persist/dist.tar.zst - persist_to_workspace: root: . paths: From 019b79125588ee121dc3fe8c87d1ca2492d7bd43 Mon Sep 17 00:00:00 2001 From: bunsenstraat Date: Thu, 22 Aug 2024 13:57:05 +0200 Subject: [PATCH 43/67] install zstd --- .circleci/config.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 387ee29962..f0e6ede965 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -419,6 +419,7 @@ jobs: - checkout - attach_workspace: at: . + - run: sudo apt update && sudo apt install zstd - run: zstd -d persist/dist.tar.zst -o persist/dist.tar - run: tar -xf persist/dist.tar - run: unzip ./persist/plugin-<< parameters.plugin >>.zip From f8a9a99b90759ad7f1aac59a4dd14aa6560b3ef7 Mon Sep 17 00:00:00 2001 From: bunsenstraat Date: Thu, 22 Aug 2024 15:07:32 +0200 Subject: [PATCH 44/67] set to flaky --- .circleci/config.yml | 2 +- apps/remix-ide-e2e/src/tests/runAndDeploy.test.ts | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index d5a065c41d..a95ed97b6b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -3,7 +3,7 @@ version: 2.1 parameters: run_flaky_tests: type: boolean - default: false + default: true orbs: browser-tools: circleci/browser-tools@1.4.4 win: circleci/windows@5.0 diff --git a/apps/remix-ide-e2e/src/tests/runAndDeploy.test.ts b/apps/remix-ide-e2e/src/tests/runAndDeploy.test.ts index 8af5c611d9..b3fb9ecd65 100644 --- a/apps/remix-ide-e2e/src/tests/runAndDeploy.test.ts +++ b/apps/remix-ide-e2e/src/tests/runAndDeploy.test.ts @@ -153,7 +153,7 @@ module.exports = { .waitForElementContainsText('[data-id="treeViewLi0"]', 'uint256: 10') }, - 'Should save state after running web3 script #group4': function (browser: NightwatchBrowser) { + 'Should save state after running web3 script #flaky #group4': function (browser: NightwatchBrowser) { browser .clickLaunchIcon('settings') .waitForElementPresent('[data-id="settingsTabGenerateContractMetadataLabel"]') @@ -163,16 +163,17 @@ module.exports = { .click('.remixui_compilerConfigSection') .setValue('#evmVersionSelector', 'london') .click('*[data-id="compilerContainerCompileBtn"]') - .pause(5000) .clickLaunchIcon('udapp') .switchEnvironment('vm-london') .clickLaunchIcon('filePanel') + .waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts"]') .click('*[data-id="treeViewLitreeViewItemscripts"]') + .waitForElementVisible('*[data-id="treeViewLitreeViewItemscripts/deploy_with_web3.ts"]') .openFile('scripts/deploy_with_web3.ts') .click('[data-id="play-editor"]') .waitForElementPresent('[data-id="treeViewDivDraggableItem.states/vm-london/state.json"]') .click('[data-id="treeViewDivDraggableItem.states/vm-london/state.json"]') - .pause(100000) + .pause(1000) .getEditorValue((content) => { browser .assert.ok(content.includes('"latestBlockNumber": "0x1"'), 'State is saved') From fbfda30afc6d09fac5973ab9ba6b0b72028cee0b Mon Sep 17 00:00:00 2001 From: bunsenstraat Date: Thu, 22 Aug 2024 15:19:59 +0200 Subject: [PATCH 45/67] unflaky --- .circleci/config.yml | 2 +- apps/remix-ide-e2e/src/tests/runAndDeploy.test.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 20d48f5099..f0e6ede965 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -3,7 +3,7 @@ version: 2.1 parameters: run_flaky_tests: type: boolean - default: true + default: false orbs: browser-tools: circleci/browser-tools@1.4.4 win: circleci/windows@5.0 diff --git a/apps/remix-ide-e2e/src/tests/runAndDeploy.test.ts b/apps/remix-ide-e2e/src/tests/runAndDeploy.test.ts index b3fb9ecd65..fc61df37b3 100644 --- a/apps/remix-ide-e2e/src/tests/runAndDeploy.test.ts +++ b/apps/remix-ide-e2e/src/tests/runAndDeploy.test.ts @@ -153,7 +153,7 @@ module.exports = { .waitForElementContainsText('[data-id="treeViewLi0"]', 'uint256: 10') }, - 'Should save state after running web3 script #flaky #group4': function (browser: NightwatchBrowser) { + 'Should save state after running web3 script #group4': function (browser: NightwatchBrowser) { browser .clickLaunchIcon('settings') .waitForElementPresent('[data-id="settingsTabGenerateContractMetadataLabel"]') From 3349be1f7fa5be82a4f012673a48262ccb9483c8 Mon Sep 17 00:00:00 2001 From: drafish Date: Wed, 5 Jun 2024 15:15:40 +0800 Subject: [PATCH 46/67] add quick-dapp plugin --- apps/quick-dapp/.eslintrc | 3 + apps/quick-dapp/README.md | 134 ++++ apps/quick-dapp/package.json | 11 + apps/quick-dapp/project.json | 70 ++ apps/quick-dapp/src/App.css | 146 ++++ apps/quick-dapp/src/App.tsx | 56 ++ apps/quick-dapp/src/actions/index.ts | 320 +++++++++ apps/quick-dapp/src/assets/edit-dapp.png | Bin 0 -> 13764 bytes .../src/components/ContractGUI/index.tsx | 128 ++++ .../src/components/CreateInstance/index.tsx | 100 +++ .../src/components/DeployPanel/index.tsx | 258 +++++++ .../src/components/DeployPanel/theme.tsx | 157 +++++ .../src/components/EditInstance/index.tsx | 76 ++ .../src/components/EditableText/index.tsx | 76 ++ .../src/components/LoadingScreen/index.tsx | 31 + .../components/Container/Container.tsx | 69 ++ .../components/Container/index.ts | 2 + .../components/Item/Item.tsx | 120 ++++ .../Item/components/Action/Action.tsx | 31 + .../Item/components/Action/index.ts | 2 + .../Item/components/Handle/Handle.tsx | 20 + .../Item/components/Handle/index.ts | 1 + .../Item/components/Remove/Remove.tsx | 19 + .../Item/components/Remove/index.ts | 1 + .../components/Item/components/index.ts | 3 + .../components/Item/index.ts | 2 + .../MultipleContainers/components/index.ts | 3 + .../components/MultipleContainers/index.tsx | 653 ++++++++++++++++++ .../multipleContainersKeyboardCoordinates.ts | 114 +++ apps/quick-dapp/src/contexts/index.ts | 3 + apps/quick-dapp/src/index.css | 13 + apps/quick-dapp/src/index.html | 16 + apps/quick-dapp/src/main.tsx | 9 + apps/quick-dapp/src/polyfills.ts | 7 + apps/quick-dapp/src/profile.json | 19 + apps/quick-dapp/src/reducers/state.ts | 33 + apps/quick-dapp/src/remix-client.ts | 32 + apps/quick-dapp/tsconfig.app.json | 23 + apps/quick-dapp/tsconfig.json | 16 + apps/quick-dapp/webpack.config.js | 90 +++ apps/quick-dapp/yarn.lock | 70 ++ apps/remix-ide/project.json | 2 +- .../src/assets/img/quickDappLogo.webp | Bin 0 -> 3474 bytes apps/remix-ide/src/remixAppManager.js | 2 +- libs/remix-ui/run-tab/src/lib/run-tab.tsx | 2 +- 45 files changed, 2940 insertions(+), 3 deletions(-) create mode 100644 apps/quick-dapp/.eslintrc create mode 100644 apps/quick-dapp/README.md create mode 100644 apps/quick-dapp/package.json create mode 100644 apps/quick-dapp/project.json create mode 100644 apps/quick-dapp/src/App.css create mode 100644 apps/quick-dapp/src/App.tsx create mode 100644 apps/quick-dapp/src/actions/index.ts create mode 100644 apps/quick-dapp/src/assets/edit-dapp.png create mode 100644 apps/quick-dapp/src/components/ContractGUI/index.tsx create mode 100644 apps/quick-dapp/src/components/CreateInstance/index.tsx create mode 100644 apps/quick-dapp/src/components/DeployPanel/index.tsx create mode 100644 apps/quick-dapp/src/components/DeployPanel/theme.tsx create mode 100644 apps/quick-dapp/src/components/EditInstance/index.tsx create mode 100644 apps/quick-dapp/src/components/EditableText/index.tsx create mode 100644 apps/quick-dapp/src/components/LoadingScreen/index.tsx create mode 100644 apps/quick-dapp/src/components/MultipleContainers/components/Container/Container.tsx create mode 100644 apps/quick-dapp/src/components/MultipleContainers/components/Container/index.ts create mode 100644 apps/quick-dapp/src/components/MultipleContainers/components/Item/Item.tsx create mode 100644 apps/quick-dapp/src/components/MultipleContainers/components/Item/components/Action/Action.tsx create mode 100644 apps/quick-dapp/src/components/MultipleContainers/components/Item/components/Action/index.ts create mode 100644 apps/quick-dapp/src/components/MultipleContainers/components/Item/components/Handle/Handle.tsx create mode 100644 apps/quick-dapp/src/components/MultipleContainers/components/Item/components/Handle/index.ts create mode 100644 apps/quick-dapp/src/components/MultipleContainers/components/Item/components/Remove/Remove.tsx create mode 100644 apps/quick-dapp/src/components/MultipleContainers/components/Item/components/Remove/index.ts create mode 100644 apps/quick-dapp/src/components/MultipleContainers/components/Item/components/index.ts create mode 100644 apps/quick-dapp/src/components/MultipleContainers/components/Item/index.ts create mode 100644 apps/quick-dapp/src/components/MultipleContainers/components/index.ts create mode 100644 apps/quick-dapp/src/components/MultipleContainers/index.tsx create mode 100644 apps/quick-dapp/src/components/MultipleContainers/multipleContainersKeyboardCoordinates.ts create mode 100644 apps/quick-dapp/src/contexts/index.ts create mode 100644 apps/quick-dapp/src/index.css create mode 100644 apps/quick-dapp/src/index.html create mode 100644 apps/quick-dapp/src/main.tsx create mode 100644 apps/quick-dapp/src/polyfills.ts create mode 100644 apps/quick-dapp/src/profile.json create mode 100644 apps/quick-dapp/src/reducers/state.ts create mode 100644 apps/quick-dapp/src/remix-client.ts create mode 100644 apps/quick-dapp/tsconfig.app.json create mode 100644 apps/quick-dapp/tsconfig.json create mode 100644 apps/quick-dapp/webpack.config.js create mode 100644 apps/quick-dapp/yarn.lock create mode 100644 apps/remix-ide/src/assets/img/quickDappLogo.webp diff --git a/apps/quick-dapp/.eslintrc b/apps/quick-dapp/.eslintrc new file mode 100644 index 0000000000..2d85f9fa66 --- /dev/null +++ b/apps/quick-dapp/.eslintrc @@ -0,0 +1,3 @@ +{ + "extends": "../../.eslintrc.json", +} \ No newline at end of file diff --git a/apps/quick-dapp/README.md b/apps/quick-dapp/README.md new file mode 100644 index 0000000000..ff8a5ce950 --- /dev/null +++ b/apps/quick-dapp/README.md @@ -0,0 +1,134 @@ +# Remix LearnEth Plugin + +## Available Scripts + +In the project directory, you can run: + +### `npm run serve:plugin --plugin=learneth` + +Runs the app in the development mode.\ +Open [http://localhost:2024](http://localhost:2024) to view it in the browser. + +The page will reload if you make edits.\ +You will also see any lint errors in the console. + +### `npm run build:plugin --plugin=learneth` + +Builds the app for production to the `dist/apps/learneth` folder.\ +It correctly bundles React in production mode and optimizes the build for the best performance. + +The build is minified and the filenames include the hashes.\ +Your app is ready to be deployed! + +## Loading the plugin in remix + +When testing with localhost you should use the HTTP version of either REMIX or REMIX ALPHA. Click on the plugin manager icon and +add the plugin 'Connect to a local plugin'. Your plugin will be at http://localhost:2024/. + +## Setting up the REMIX IDE for working with the plugin + +The plugin only works when a compiler environment is loaded as well, for example on the home screen of the IDE you select 'Solidity' or 'Vyper'. Without this the plugin +cannot compile and test files in the workshops. + +## Setting up your Github workshops repo + +You can create your own workshops that can be imported in the plugin. +When importing a github repo the plugin will look for a directory structure describing the workshops. +For example: https://github.com/ethereum/remix-workshops + +### Root directories + +Root directories are individual workshops, the name used will be the name of the workshop unless you override this with the name property in the config.yml. + +### README.md + +The readme in each directory contains an explanation of what the workshop is about. If an additional summary property is provided in the config.yml that will be used in the overview section of the plugin. + +### config.yml + +This config file contains metadata describing some properties of your workshop, for example + +``` +--- +id: someid +name: my workshop name +summary: something about this workshop +level: 4 +tags: + - solidity + - beginner +``` + +Level: a level of difficulty indicator ( 1 - 5 ) + +Tags: an array of tags + +id: this is used by the system to let REMIX call startTutorial(repo,branch,id). See below for more instructions. + +### Steps + +Each workshop contains what we call steps. +Each step is a directory containing: + +- a readme describing the step, what to do. +- sol files: + - these can be sol files and test sol files. The test files should be name yoursolname_test.sol + - ANSWER files: these are named yoursolname_answer.sol and can be used to show the solution or the correct answer. The plugin will load the + file in the IDE when a user clicks on 'Show Answer' +- js files +- vyper files + +## Functions to call the plugin from the IDE + +### Add a repository: + +``` +addRepository(repoName, branch) +``` + +### Start a tutorial + +``` +startTutorial(repoName,branch,id) +``` + +You don't need to add a separate addRepository before calling startTutorial, this call will also add the repo. + +_Parameters_ + +id: this can be two things: + +- type of number, it specifies the n-th tutorial in the list +- type of string, this refers to the ID parameter in the config.yml file in the tutorial + for example: + +``` +--- +id: basics +name: 1 Basics of Solidity +summary: Some basic functions explained +level: 4 +tags: + - solidity +``` + +### How to call these functions in the REMIX IDE + +``` +(function () { +try { + // You don't need to add a separate addRepository before calling startTutorial, this is just an example + remix.call('LearnEth', 'addRepository', "ethereum/remix-workshops", "master") + remix.call('LearnEth', 'startTutorial', "ethereum/remix-workshops", "master", "basics") + remix.call('LearnEth', 'startTutorial', "ethereum/remix-workshops", "master", 2) +} catch (e) { + console.log(e.message) +} +})() +``` + +Then call this in the REMIX console + +``` +remix.exeCurrent() +``` diff --git a/apps/quick-dapp/package.json b/apps/quick-dapp/package.json new file mode 100644 index 0000000000..ed130ad7dc --- /dev/null +++ b/apps/quick-dapp/package.json @@ -0,0 +1,11 @@ +{ + "name": "quick-dapp", + "version": "1.0.0", + "main": "index.js", + "license": "MIT", + "dependencies": { + "@dnd-kit/core": "^6.1.0", + "@dnd-kit/sortable": "^8.0.0", + "@drafish/surge-client": "^1.1.1" + } +} diff --git a/apps/quick-dapp/project.json b/apps/quick-dapp/project.json new file mode 100644 index 0000000000..8ca9b6c42f --- /dev/null +++ b/apps/quick-dapp/project.json @@ -0,0 +1,70 @@ +{ + "name": "quick-dapp", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "sourceRoot": "apps/quick-dapp/src", + "projectType": "application", + "implicitDependencies": [], + "targets": { + "build": { + "executor": "@nrwl/webpack:webpack", + "outputs": ["{options.outputPath}"], + "defaultConfiguration": "development", + "dependsOn": ["install"], + "options": { + "compiler": "babel", + "outputPath": "dist/apps/quick-dapp", + "index": "apps/quick-dapp/src/index.html", + "baseHref": "./", + "main": "apps/quick-dapp/src/main.tsx", + "polyfills": "apps/quick-dapp/src/polyfills.ts", + "tsConfig": "apps/quick-dapp/tsconfig.app.json", + "assets": ["apps/quick-dapp/src/profile.json", "apps/quick-dapp/src/assets/edit-dapp.png"], + "styles": ["apps/quick-dapp/src/index.css"], + "scripts": [], + "webpackConfig": "apps/quick-dapp/webpack.config.js" + }, + "configurations": { + "development": { + }, + "production": { + } + } + }, + "lint": { + "executor": "@nrwl/linter:eslint", + "outputs": ["{options.outputFile}"], + "options": { + "lintFilePatterns": ["apps/quick-dapp/**/*.ts"], + "eslintConfig": "apps/quick-dapp/.eslintrc" + } + }, + "install": { + "executor": "nx:run-commands", + "options": { + "commands": [ + "cd apps/quick-dapp && yarn" + ], + "parallel": false + } + }, + "serve": { + "executor": "@nrwl/webpack:dev-server", + "defaultConfiguration": "development", + "options": { + "buildTarget": "quick-dapp:build", + "hmr": true, + "baseHref": "/" + }, + "configurations": { + "development": { + "buildTarget": "quick-dapp:build:development", + "port": 2025 + }, + "production": { + "buildTarget": "quick-dapp:build:production" + } + } + } + }, + "tags": [] +} diff --git a/apps/quick-dapp/src/App.css b/apps/quick-dapp/src/App.css new file mode 100644 index 0000000000..1fa7e5637a --- /dev/null +++ b/apps/quick-dapp/src/App.css @@ -0,0 +1,146 @@ +/* You can add global styles to this file, and also import other style files */ + +.item-wrapper { + transform: translate3d(var(--translate-x, 0), var(--translate-y, 0), 0) + scaleX(var(--scale-x, 1)) scaleY(var(--scale-y, 1)); + transform-origin: 0 0; + touch-action: manipulation; + + &:hover { + .item-remove { + visibility: visible; + } + } +} + +.item-remove { + visibility: hidden; + top: 5px; + right: 5px; + width: 20px; + height: 20px; + background-color: rgba(0, 0, 0, 0.3); + + &:active { + background-color: rgba(255, 70, 70, 0.9); + } + + svg { + fill: #fff; + } +} + +.item-action { + touch-action: none; + outline: none !important; + appearance: none; + background-color: transparent; + -webkit-tap-highlight-color: transparent; + + @media (hover: hover) { + &:hover { + background-color: var(--action-background, rgba(0, 0, 0, 0.05)); + + svg { + fill: #6f7b88; + } + } + } + + svg { + overflow: visible; + fill: #919eab; + } + + &:active { + background-color: var(--background, rgba(0, 0, 0, 0.05)); + + svg { + fill: var(--fill, #788491); + } + } + + &:focus-visible { + outline: none; + box-shadow: 0 0 0 2px rgba(255, 255, 255, 0), + 0 0px 0px 2px #4c9ffe; + } +} + +.container { + flex-direction: column; + + &.placeholder { + justify-content: center; + align-items: center; + cursor: pointer; + } + + &:focus-visible { + border-color: transparent; + box-shadow: 0 0 0 2px rgba(255, 255, 255, 0), 0 0px 0px 2px #4c9ffe; + } +} + + +.container-header { + &:hover { + .container-actions > * { + opacity: 1 !important; + } + } +} + +.container-actions { + > *:first-child:not(:last-child) { + opacity: 0; + + &:focus-visible { + opacity: 1; + } + } +} + +.instance-input { + background-color: var(--custom-select) !important; + color: #dfe1ea !important; + font-size: 10px; +} +.has-args { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} + +.udapp_intro { + overflow: hidden; + text-overflow: ellipsis; + display: -webkit-box; + white-space: pre-wrap; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; +} +.udapp_intro:hover { + -webkit-line-clamp: inherit; +} +.cursor_pointer { + cursor: pointer; +} +.cursor_pointer:hover { + color: var(--secondary); +} +.custom-dropdown-items { + padding: 0.25rem 0.25rem; + border-radius: .25rem; + background: var(--custom-select); +} + +.custom-dropdown-items a { + border-radius: .25rem; + text-transform: none; + text-decoration: none; + font-weight: normal; + font-size: 0.875rem; + padding: 0.25rem 0.25rem; + width: auto; + color: var(--text); +} diff --git a/apps/quick-dapp/src/App.tsx b/apps/quick-dapp/src/App.tsx new file mode 100644 index 0000000000..5adacb2e2f --- /dev/null +++ b/apps/quick-dapp/src/App.tsx @@ -0,0 +1,56 @@ +import React, { useEffect, useReducer } from 'react'; +import CreateInstance from './components/CreateInstance'; +import EditInstance from './components/EditInstance'; +import DeployPanel from './components/DeployPanel'; +import LoadingScreen from './components/LoadingScreen'; +import { appInitialState, appReducer } from './reducers/state'; +import { + connectRemix, + initDispatch, + updateState, + selectTheme, +} from './actions'; +import { AppContext } from './contexts'; +import remixClient from './remix-client'; +import './App.css'; + +function App(): JSX.Element { + const [appState, dispatch] = useReducer(appReducer, appInitialState); + useEffect(() => { + updateState(appState); + }, [appState]); + useEffect(() => { + initDispatch(dispatch); + updateState(appState); + connectRemix().then(() => { + remixClient.call('theme', 'currentTheme').then((theme: any) => { + selectTheme(theme.name); + }); + remixClient.on('theme', 'themeChanged', (theme: any) => { + selectTheme(theme.name); + }); + }); + }, []); + return ( + + {Object.keys(appState.instance.abi).length > 0 ? ( +
+ + +
+ ) : ( +
+ +
+ )} + +
+ ); +} + +export default App; diff --git a/apps/quick-dapp/src/actions/index.ts b/apps/quick-dapp/src/actions/index.ts new file mode 100644 index 0000000000..5990d13cec --- /dev/null +++ b/apps/quick-dapp/src/actions/index.ts @@ -0,0 +1,320 @@ +import axios from 'axios'; +import { omitBy } from 'lodash'; +import { execution } from '@remix-project/remix-lib'; +import SurgeClient from '@drafish/surge-client'; +import remixClient from '../remix-client'; +import { themeMap } from '../components/DeployPanel/theme'; + +const { encodeFunctionId } = execution.txHelper; + +const surgeClient = new SurgeClient({ + proxy: 'https://vercel-proxy-bice-six.vercel.app', + onError: (err: Error) => { + console.log(err); + }, +}); + +let dispatch: any, state: any; + +export const initDispatch = (_dispatch: any) => { + dispatch = _dispatch; +}; + +export const updateState = (_state: any) => { + state = _state; +}; + +export const connectRemix = async () => { + await dispatch({ + type: 'SET_LOADING', + payload: { + screen: true, + }, + }); + + await remixClient.onload(); + + await dispatch({ + type: 'SET_LOADING', + payload: { + screen: false, + }, + }); +}; + +export const saveDetails = async (payload: any) => { + const { abi, userInput, natSpec } = state.instance; + + await dispatch({ + type: 'SET_INSTANCE', + payload: { + abi: { + ...abi, + [payload.id]: { + ...abi[payload.id], + details: + natSpec.checked && !payload.details + ? natSpec.methods[payload.id] + : payload.details, + }, + }, + userInput: { + ...omitBy(userInput, (item) => item === ''), + methods: omitBy( + { + ...userInput.methods, + [payload.id]: payload.details, + }, + (item) => item === '' + ), + }, + }, + }); +}; + +export const saveTitle = async (payload: any) => { + const { abi } = state.instance; + + await dispatch({ + type: 'SET_INSTANCE', + payload: { + abi: { + ...abi, + [payload.id]: { ...abi[payload.id], title: payload.title }, + }, + }, + }); +}; + +export const getInfoFromNatSpec = async (value: boolean) => { + const { abi, userInput, natSpec } = state.instance; + const input = value + ? { + ...natSpec, + ...userInput, + methods: { ...natSpec.methods, ...userInput.methods }, + } + : userInput; + Object.keys(abi).forEach((id) => { + abi[id].details = input.methods[id] || ''; + }); + await dispatch({ + type: 'SET_INSTANCE', + payload: { + abi, + title: input.title || '', + details: input.details || '', + natSpec: { ...natSpec, checked: value }, + }, + }); +}; + +export const deploy = async (payload: any, callback: any) => { + const surgeToken = localStorage.getItem('__SURGE_TOKEN'); + const surgeEmail = localStorage.getItem('__SURGE_EMAIL'); + let isLogin = false; + if (surgeToken && surgeEmail === payload.email) { + try { + await surgeClient.whoami(); + isLogin = true; + } catch (error) { + /* empty */ + } + } + if (!isLogin) { + try { + await surgeClient.login({ + user: payload.email, + password: payload.password, + }); + localStorage.setItem('__SURGE_EMAIL', payload.email); + localStorage.setItem('__SURGE_PASSWORD', payload.password); + localStorage.setItem('__DISQUS_SHORTNAME', payload.shortname); + } catch (error: any) { + callback({ code: 'ERROR', error: error.message }); + return; + } + } + + const { data } = await axios.get( + 'https://remix-dapp.pages.dev/manifest.json' + ); + const { src, file, css, assets } = data['index.html']; + const paths = [src, file, ...css, ...assets]; + + const instance = state.instance; + + const files: Record = { + 'dir/instance.json': JSON.stringify({ + ...instance, + shortname: payload.shortname, + shareTo: payload.shareTo, + }), + }; + + // console.log( + // JSON.stringify({ + // ...instance, + // shareTo: payload.shareTo, + // }) + // ); + + for (let index = 0; index < paths.length; index++) { + const path = paths[index]; + const resp = await axios.get(`https://remix-dapp.pages.dev/${path}`); + files[`dir/${path}`] = resp.data; + } + + files['dir/index.html'] = files['dir/index.html'].replace( + 'assets/css/themes/remix-dark_tvx1s2.css', + themeMap[instance.theme].url + ); + + try { + await surgeClient.publish({ + files, + domain: `${payload.subdomain}.surge.sh`, + onProgress: ({ + id, + progress, + file, + }: { + id: string; + progress: number; + file: string; + }) => { + // console.log({ id, progress, file }); + }, + onTick: (tick: string) => {}, + }); + } catch (error) { + callback({ code: 'ERROR', error: 'this domain belongs to someone else' }); + return; + } + + callback({ code: 'SUCCESS', error: '' }); + return; +}; + +export const initInstance = async ({ + methodIdentifiers, + devdoc, + ...payload +}: any) => { + const functionHashes: any = {}; + const natSpec: any = { checked: false, methods: {} }; + if (methodIdentifiers && devdoc) { + for (const fun in methodIdentifiers) { + functionHashes[`0x${methodIdentifiers[fun]}`] = fun; + } + natSpec.title = devdoc.title; + natSpec.details = devdoc.details; + Object.keys(functionHashes).forEach((hash) => { + const method = functionHashes[hash]; + if (devdoc.methods[method]) { + const { details, params, returns } = devdoc.methods[method]; + const detailsStr = details ? `@dev ${details}` : ''; + const paramsStr = params + ? Object.keys(params) + .map((key) => `@param ${key} ${params[key]}`) + .join('\n') + : ''; + const returnsStr = returns + ? Object.keys(returns) + .map( + (key) => + `@return${/^_\d$/.test(key) ? '' : ' ' + key} ${returns[key]}` + ) + .join('\n') + : ''; + natSpec.methods[hash] = [detailsStr, paramsStr, returnsStr] + .filter((str) => str !== '') + .join('\n'); + } + }); + } + + const abi: any = {}; + payload.abi.forEach((item: any) => { + if (item.type === 'function') { + item.id = encodeFunctionId(item); + abi[item.id] = item; + } + }); + const ids = Object.keys(abi); + const items = + ids.length > 2 + ? { + A: ids.slice(0, ids.length / 2 + 1), + B: ids.slice(ids.length / 2 + 1), + } + : { A: ids }; + await dispatch({ + type: 'SET_INSTANCE', + payload: { + ...payload, + abi, + items, + containers: Object.keys(items), + natSpec, + }, + }); +}; + +export const resetInstance = async () => { + const abi = state.instance.abi; + const ids = Object.keys(abi); + ids.forEach((id) => { + abi[id] = { ...abi[id], title: '', details: '' }; + }); + const items = + ids.length > 1 + ? { + A: ids.slice(0, ids.length / 2 + 1), + B: ids.slice(ids.length / 2 + 1), + } + : { A: ids }; + await dispatch({ + type: 'SET_INSTANCE', + payload: { + items, + containers: Object.keys(items), + title: '', + details: '', + abi, + }, + }); +}; + +export const emptyInstance = async () => { + await dispatch({ + type: 'SET_INSTANCE', + payload: { + name: '', + address: '', + network: '', + abi: {}, + items: {}, + containers: [], + title: '', + details: '', + theme: 'Dark', + userInput: { methods: {} }, + natSpec: { checked: false, methods: {} }, + }, + }); +}; + +export const selectTheme = async (selectedTheme: string) => { + await dispatch({ type: 'SET_INSTANCE', payload: { theme: selectedTheme } }); + + const linkEles = document.querySelectorAll('link'); + const nextTheme = themeMap[selectedTheme]; // Theme + for (const link of linkEles) { + if (link.href.indexOf('/assets/css/themes/') > 0) { + link.href = 'https://remix.ethereum.org/' + nextTheme.url; + document.documentElement.style.setProperty('--theme', nextTheme.quality); + break; + } + } +}; diff --git a/apps/quick-dapp/src/assets/edit-dapp.png b/apps/quick-dapp/src/assets/edit-dapp.png new file mode 100644 index 0000000000000000000000000000000000000000..445ce2a218b6101b58d934b4524f579b2afc75bc GIT binary patch literal 13764 zcmd^`^K)fU*XKLx*yz}H(y?vZwrx8%wr$%^$LZKk$L`pe+s`}iOx4uX`~&mDxwUJb zjdk`tSfB4&J5oVT93BQ6=G(V#@RAZDO5eVLPyx$TP~U;ST&Y%vzzPFPVPOSHVPQfA zCwntX8`E#!C=+bs`=o^&(S~P!3QG`$6GnuIBcW-8NJ=Mhi6~sx7ZPmTz5MifJbWPq z9c|4l>LbL)Uf03i%*+IU77M)3JTb|(wuPrElH(-|m&M5o@GgQt)^%_5 zBP+D=<{|i6^3 z;HtYFg=afY2WEg5QHmuPA^ofnuq;kUF)POM=6S63UGCa$;y!m>ZSlXz&2b*VpERDK z3~yi|W-X*V%Ki!cJ;2}_2qV$)YRvb??Uiyf_aYpN{Hi(l>uu+NO0U1Y_o_?kPupG( z>kJg`W(*?WAc6u&*NWipzRmjcbigtaI2x#sk`oaWXi$JW2_fm>LYX)h1r*f3O8Ear zB@&0m-*+%jButL-b%P~|UP3}(A2ui#clV-ElSWBr7shfjGVntvHc3=)a1eK7hZODa zWK{0l#D@_7OmKh%A)<1hO==7ZAl!8X4=LtBXkhs_#1$dX1_Uo9HK1iYu>tYPqeQ9S zfmZk90UK=!%1^)m4IM>BO1$M5nhyZZ+8zvS#C;;E`R~FwfM(-|YhWY&n-d8s(Fu~5 ziUv3;zPNzI#6FTV*uUuzfQ_#5DNKQe^zTDKNqXWMS^isyO+jEIy!+y6;HVzBK>Ol^ zY5%hX+)!gyZvWMTfh0aTF_!Z#jhK&VxRgRS2d`bt1A}aZe!Vzu1dOO+&SSZFCP;t) zR7QcQ;7_~PO*1@s1GFTdJ1AJ#;c$;Ct9#Ckkd$?OI{jW9sa`06j*^_xoA~zb?pJqN zuHeAM3nONySc@nb6IB%|->RL42IjMUv$To|%ln7;R|R5;GcqnN&%pvR3JPGXoHG27 zn3x0^1OJL~hKq@g7mul-VOf%|WoKg}>gVX=A3ag3(kUOOp;rua)Z=t!EIY>Zek8ukH;i@}1eKKJsU8pQevbzi%-*}T3mY14U4 zivIhT1VjOT5_`Y&zi9M6gI8uZH=}ho`c%0-KS4b1atQvcr%XmfMTyJl<;rUEQTDi^ zzCB%tIZ44R+xcJ+5fMq1H8mxjt%YTtS-HM1$9*D+BjTyN3JMB(ytJ^-ZZ1aH_iY1O zaM*}wD8x@KzvS@v!)QX&`VT9ss2lD!Y_%|!`QLE0w6z=#c0r^wAEp7SRZMn+BHd3_ z?sE$Z!IH|QMyI#v%hXnVJw14NzR$g~UW^Z4-gUjD5vdG&Nu#laCuis~**v04H;2c0 zN_|->8HY2~LSkxcd>^~KuJ4NrlZ>WXAPAQ`QCVbUY!6O34UUe_AL{yAjE14_H>mYa z57;&voe-)ih_(~$PW{iTNwal3A0^Zi93|!^l^@(~_6wftrphI}a@pg@J`1o}3F*nj zF5FN>HGOYEwKE7JA|kt?X?=0CvkLX-N~)TXmwh{xjI9;v2pZva;S78qBFNbK{+SjZ z3$YK|TBG@XZ=Vd`t8-@@jdkIfo9-YN7ifNFLRtNavfmR^B%03SGO2isgqUP>Jd^Qh zJ2dX>#il*2z4C}IPR~b4Qf_eCidyY+mgX-s3fk*FS@l>{Q}0~g@$>S#R;CT6DlA1&CTCpy+*>j&s~QLEh{%lqS|P-L${@ zYtR3w(9+@ZB9*+|8;Y|M#nfWJrB=5SQ0Mo?sid@khV0jL=w5kpl%`*h#RN+JYKjPN zUo$}d@r(OD802@gM|7l!NSEbC(z`wS( zn8)V(9pP%rcDxO(dBe~;fPt@9Gg^dCtVoczg_F+z-2>-R)p~^_J9kWfVL{V+MQmU| z&{npEnAc7BJ8J7=`&LzGX!^4Fx8Rh9>6x+LgKNqZsynOLM#R(8Y}%gQZa(4Z=^CyJ zwR&xOni`oU&({NB#I13Q&o$@9RgQm@rIXPu{e!4d+d` z(%6$B7U$<>5aVHFidkf{|12)A1B}BF6{AP;B`O*}h= zXj}nmB~z*A3^a5tlKWuZaIaJ+@%>EY-0V@W!}%`dT4~g)L3`|gq|&L8^ag|rQ3-%<_Xl^c5-D0ygw@ZUP$*@8nq^yZ|7{tC>iyq%xDy6;iK+ubLxb#yT^cJ< zwQDK^KPbDx8GOG~Rrq`&x?CI)$=`=+$=aqfT|D|~TfbK%myK_}+@(xDZ?WrFWeG?h z+iH1zN1mge%zL~)>>h;u0aavHt=ATa2$_8P(`;_a5l6iaEpajt&TU5r-Oc-jBE-tt zidIxBGb=vc!p(P;+JHS-k|JV{=K{uR@Qs)E!=E6Aj;WOrSJO_pRF*`#NLSO7Tp96p zWDTWL?a4r!9K7}RS>8Fz*vJU#OG{dj??=N;oDtEqL#KP&;QY#S2smk3Y2ov_s;a!U zHVrfL)D;OuJu8-E1GhK|GP2~#3|Lk*x=CaWk+cfC{Ci?byYs=0CYJ=$3e4}?lDMc=RxDj!*)xNwNIMbl$@~JT2{b53 zND+2PYY$D!<|`EW49_xpxs5`r%ztoJ^q!%u3%Q#6^j15?aFe8@wemM}Z9c&8bwR}%88tA=2C6~b%AD`+8r)ap!gbS`yb;bKB|LOw zW8l+2hIGQcg2_rtN~+SaMyDEItNHi`w=!8gW!9f{1|oy^XL_D_b$WE5T2VCRa5)Pj z?w8oNmF#|MYiCZ{?}*z~rBpLp8zx$xMICFF@yEVhBwB$FYxB8@^I#;+bCn=3O*}AA zIqkXhKm*Qg3i3U`GXCNkrwhsJx>;WY*H({m`6xCW?gDsx90;0@c;@6&=rUls(s^RW!oe`v8|SyO6SqT2cT1`E zXt6PjoL$5+JTleL(2?yccCCajbow`}O)cXXM~R0tD!x2=1g}`dwZy~OAgtQj>cGU z6yzSUvZ*^%s))2TiI7i!E7HJiYFb)aD|*e%OfAmbJ0 zh8K*KE?!?=UJy49?>HoHpywk1I|mJL_apLDaCiEDLhn4h4y77F1?=-{tJ)VBs~XYv z`)|8LVJo)H9kMq?d)J=L;9y{ivyM|mhTTIy7V?T+yD+&(1)*v~{kcX80P=_Vf9=0@4_Chn^#o zl1sF8RZGTf<`*qf)9{)Q3oh)d>m!#nh2(zCDhV1od z#=RQ-69()JPiq3a-X>F**JHB!hxR4XFN($wUC`adT~AWf^tD5~p_OygMm=3wfB7>V zHXA`=y}QZ7CR)?u+h^o+e3;!_2OX0LDe>TwSN3f5IWV$3C9b;8>m+I4W5m>eAXHje zUM(TG{<>OygjZAiEde{-SW^G-)aPyybCXqmk*!m`RxjA|VLTIC26vrDzK#aY*Lrna z`?s~~6fHBi)s!Z@O!A`1spdIsKdac_NX9hOvJ=eqX#r94XH)SWvvh2Fi7h~c?Rd|YPGZ$OdW}zMtT^+jPAa_MVMLt2@ zNdICgq9sQDJVo2Kwy{w4=m`^6#F3^(AipzK(B^61{Shm*N641)&_670z-~dT$OEPvt+p9uOyCT^LoC?m>5fn z{ocZn&L7tR4`kr~`b|UV;4`jnq(A}@5WgrvM0W`V%0<|JQ?hoKT8oF~JHUkqh?uaTBq~8FVY%h5_?z+alAz+@U0Rga5j+y!(_`YH z1|OA@_f)04f(J513Mff^SF7HD^Y{1H;qgXWsneNt&F)N4(eU8V`x@9toqo8#&#!Jq z1M)~?G3UCc(}2*wSHHPju0t|!p`}c^HM^aXfxElA@y2qUg1-7n9isim2_lfRY?40z z=J`Y)_dPKS2@BiKzwGXA^Fkp&k6cjX4w)198jQyQVn?3z{Zae;p3+iT){wz{-~-cF zJ$|QmVPa`|UfH7m(m(5I$qJV5yJ|1E55 z`>{_hGjwaN_D9N)8pu4p@b2LsnjL0zwLf%!MHYzz@k0yfl7M`Do{l28KK)&bnb&5w zz2)=#Vn6e^U9?Q+_6PX~GSZ)mL8qy{Kug3>L4QW(@1Z0rsCcMtZHN^GcIUB)DnzB# zsauXB`arVD*rn+#`C4>pDlPLGCw4l&Vf=II3k(gZtw%06)4A>WKtVxg7ypaQVjtbk zjT}nvE?^l37mbCatTN{rx*hP3XL1$aAby&m5d9W6FhIh_!LB#nV7IWh7Y34_T8(bp zbp+I5r|s8~wb7^A!NDOB6BX9+Om?d!H#xbQreLP1``#+DDOTgK2_vSB%b@_0M>diH zY$WvAZD>-eVH3nK_%J>Gyql~`$Sc`WU=enGt(r;YP3r!DlWFrl`0h9*R$}!!I9y3<6*nUC(qvA ze!ansGKYW~d{^{&p0D2F<#q!ePOdkIIxIs0(A77ctJ%1x?R~vGmMHNvH8Fi6sR$Vo zxke4z;=v$S@M9(=C9mkD!@JzbV6w(&baq-w7?>@oX7I*)+n=phpw(|#PsGJFIcL^l zHW5dK(NAcCeVhi%&#pr|h0+Wo>y!PKEU2K>;&F{WnzBumI?@=K;KSb-xW`-=&;lxjc?qTBIwcQCG8>oT&9o ztL}Hmy8VG3?{c4K0pJ^-!`g5UTOvHzHS_+_NfQt>C%e6I7xAaXhny1Q5?+_4!*j`G z0G`yfg%t`0MyYtn*O+}~hyPpll|-#>$28#-}IPlxPSuf zjTQJDvP^|+V-=jzZHF^$lUC6FPvi_ z>o3kCTavCtp5*3#saR*8TwYn)1Bb|m*Ztni!XB)@)r7t{w_V`U?0<2#ML}ath$s6r z*P6DCtri@7lBKs=EdiiQvDI#)ba&pV&CzJ^iXq0S{aXDaTxl^7jU_Sjd$0zFEUvPU zcX_SLnPS;yHRANAITi88<2fB0*D@qch27^uNEu;sGmCXNLhA<|AEZ7$}$ZJJ)r`WKKYGc$&0%rEeIc;Gu@YGxSC-j6N3JkFdU7fW*P;>Vh3P zm)fN+=F=qv(cn3Wjw)(TmqM?iqNSNuSrQ@#VMF1Kdv7AOE2>0j%JYS0JAV8k#l`?C zX62MU1$bwjc#6_eE4k99KuM0#2VTzRqJ8k(j_Km(B_b00U3W(7Hh!3Ex$}(q$PgjjB$i=Tdrev8m^7oo45l zJ@yG!^)!FIR9QYbZus$mAjZ{9>i85EmSzD9iZ5#5CeQu3vpCf)UF6NJs4%mSh z@oI!FbM4x@dZG8_!b>%Q0yX{-81?z*+0OytDsGm$M%!;-6$NR3Apl15<^D8bnl~0I z`89m^FkT1k?Uemv6f5?Noe`QBA?VNaeNO^C=^^}LiL9Uj61den=ndq+8i!zNO4&iR zJ|@C<5zk7mtuyq*d3dP`38dK{foy%>-Z>~?cV4~2BtGR88hh~`6>NceCa78^I{3Xn zzeMe-c;Jmi5xaxe1U+%DkpG>Qz1Q-2WTy#C5QRbt7X%0%5>(M&oiAZ`IzNj_@c@Je zOV#V-$uIGS@;PE5rJ_R_Nqzzv@YLDtioTy}#9(pD1PibM44_7eSNvWWI%tXW=f9oG@zLGIY4GU;JWbM5G?qk_Fv_#R-1q^DNOV1>etq zIo!Dd9p~~3N`B(xqoff`PC-9&Fe#*Un0@6LAH7W#2)Kr48;NL+z;Aw(dY@{iBX7Pz}E zZ62=T4Uht;k{NT{j(8sR4}x$DQP1Y4U)4H%jQHdZN-{_eA>ZU_JgSONv~lXZlJl?T zGnM(He*cPMT5w<)yD4$Vp76JZpjBh;!9YXFyJzhaDd+&UHk+ zJrQ0KXOCdJxX6|vCGC9lO;;OPY2#VOx+gi#V@LnPu>O}wW_0+(%ksKR`R)cZVL^Y+ zrwkJ0!{3;Jf&nL~Ot!h7Cl$0ZFY^H?{*dw|?=@w48zh)c=&25h4N5fIE$F*N4QvmH{YS84M)E<}h59)JSrs z-m>H@XgMO6YdxvmwVmNmvcCl`Lq9C2IpZ#3_{9`daGzmsrZc_U+xC4)r*%VDEn#OJ zUNEg@{)*og#zbV?gImp9icVhAjIBQ-1QA!r$Rlb^M%`TRrsawa)x3T{{}PoxCLw40 zPCj@rxF%g*TOH^hz>mS88*!3O+1%QksC;_@dyC~% z!bc9<+ITXw8ZbGSjad}d(CKi2N4(+{QE?%~;9({3A!%uC{qtOq1fzc?>>|SwJz|&5 z=ZGN-FUz){$D*awxtH*3bS5dxM0VO>y zXnqOCvePb5j24z$!a%758uV+I04=)z+Co$;JFRu^je3TkB}jtqo8kDHMVCLU9|%Z9 zUPFik6`q!!gb#LtE>(JUW8Mb|xafjBOhRozL)dz8*>dH|tj}FgB?YyAXC-@LMBKS; zuP3x-R{G-JoXb8>Cw3)Lihe-I+GKKW-Dgxxoa#`0xLpvSu`8X;7jSmge5!m}ff?b; zjaXROsI@hgosgVZ40U!gfZFbGgo3P;2P=S!A&{M4$?@8bxbhJ38Khy5?VOqA;f^W6bEG#TSlJ%dd)~=1+`dC?;i~ZlaxRB7V#T|fa)+vZN zIpwmUZjZ^LmJ*$NEy(?S+ysq)LbRu$XKQYCiOnR#*x;GS_N0HU1PRCE9Oyl(xm!WQ z35!y$mz<_Rf{0h9O3t$yGJ&>*AhL;Oe2Sa@6UEt4=5=tNBKXRZ0+_ORR%3lSIM}Zu z1Di@=L`_@4grij%3!_qE!P+#*>Z?7X8tA-@<(1`qj0daD5T7B6A?-bE8T>XWyP~Qp z*p<31g_q5j;scRIl_lyR!$eCWnn^7wfPLk!dl_Q?#*tN5!#@lc#$y0W66vTK8n6Ua z$vN5P1lHkV6cp^jh-kWEuCt^T%&r$}mfgq~XS9S|PS5Q`-Isd6>wM+s`o_8?oTC+P z?D~-q;<(e<*~MUvwrOgwsc5Lt(iKBP;b(1$9yFtUNX}1!`Yrq3W|R6niaTt>n*-@YMYleVk$O@ z!$V}0Pq8$I|AcmO%35#WqDRVCi>x>PrJ5`)+qik<;U&Kl-P$n!Y%D2~tQ#+P^L}%w zzU$P+nX(d5a#0WTVQZq#*p=dlDK5DOOvvj#CUV))a+XCXYO2APuSfFiljISne<6cA8YPG5$+v)tk=aRRX z;qFu%LjprZi)!hrMtS{Qdm81M@ydga zVCcIur`Jl1s!Pegf5dZrzZNW6Z(IV3b%IwKKRU-Zb=0l`^4!aLlZZK z=fxb!jhik})lFynHh+AgSx)MQHRhinoL1J&H^#I0^D3qB#HEirt7>g*;iU4|mZi~~ zw5EcNiJC;wIBy}MQMoQLXQM`s@x&Xt$* z)JqY1U|yO%1{s&()Z#Cp`cX1*87ZKvxU_`w$KhrLEG0RLv_#{_+_zSk)f&ULo9j>G zh*=#Ot8~d&Xx3yM0=Gl#Go0OO+jGBCclW(;ZvJ2V&D(;-f_e5=9;QKk5x+;Dj7xVt zB(fW&)`k!L8cdHX(<72IY*?`P9kUw^;u5v3KL|Ah5Yr-)Mrc@D#WYttjntU}){O_3 zwOI-)Yihy2JO_j3UwN#ydOBetkz46;=1`C0qeRa|7KZCSn-gxBa&TiI9j`l&7TvXC z*WKFKs~UAmAEs5&9pc=P*gM>3jBK}S@C+PbZFz!X$x{&{k3VD9xD#uO|6VdOJM{xs=N>npeiH^37t zLwt!9nT!=K>^>i}dTL6lwo@0?w`p5OEQcMIl^Mkiow2xTpm%vqfrq%LM3D;ET&;)$ z49|EQH}GJ6_+E0DIb5&IrPNgXM z=?052L-NEaK8*O19_lzYG2NdTGgHoyM`Md18Xjr&_mLq?$wZ^mkF(?Fshu1B0NR*~ zs2}svdx)#3x_nMRJ(TIC#tP?WOkPF*OU%<(W_7*;&^Z>UmpghTAm*Wqi#QO5>D-|( zI&F=Qa>aXm(?L9c#3bktdgOW>)d?H!^!3J*$MaXQ<5nM8a`Qk)CVA?&=(AKMug9d2IwU zT*-~H(`Wm8lA^VwC77}Gh@Kaf+Wf{3@kRVeX0X3|>ywP%yt2#JND<4TWg+x9 z97Gg0;mb}<2HJ_2nMkaC#UBtv6m(j<7;=l37Q~pS>3?D5kj$+wd$)jo#y|PK`W(W( zMw9*ICD=0Q;7A%6IjGL&{ll@a@8b8eD-kB85PNoQwqD*=+zp+}(8jAHJ&`tgAh(0@ zSfdtS@hgt7y^%SP+xH=~(Ma-TP&1y72LtNb3W7)bUDM0^xb|AeshfEqoW5FS*G^mM z6B)EzZ4DLN23e!d5Bv}Pp4XN)#ExhKi`!{fCv%{!{eeY0P-ln#!AW)8^lzwc zq%C50b(-B2Xpf9-f1INUa6Z^s%JcO2MM`eNdEMiGZR!?KdihIAe70UN)Ab>I#A#69 zVQa{)PJZbh^Ty-K|4UJVRwK&dq8q2#!vW6v zGU6Gp2ZsvMQ;LpTniu+N>Jg?D=AN#bV1zFuz@EsQP(jycbWzYmy2K@703r)Cig_zT ztsgiYYQjQ_;wMcX0thxqBv8xtgpHTYvxo39-+RI2#CwGgrU0>ON_nVSVz-(%)*2ww zLd~WtYw{)dd>t9{Df%ItA;5*gyBt&exCy3a{zx1iAw^r6z~KtkX2^nR(Nnm~B(8EL zM?+bvvA~bYi3g9bEsclh!`hxZ2|m0M%MfWtIvi|N$UGU42WBPJ_&^CNrWHGMBi@H^ zyDXg2B>m*RmEuup?yn`2UuwD!yR^;z<2M_Y-_3OITq4oJ&oC4pY)|>4^hIJf3C(@B5)amA$xbo<^k5 z?%lZN9CCFc1-fz41L{DH=C;~w0M54KH>SWuFrSwTo>E`f0(9C>V|Ti3wk1T*m>VwY zn>rD>JXB7scO89$E2dB{6*z4PE0yfh(Xyl{8C&Yd5%56tb8Pu4>|25==s%%?s%04O zo&U-~e775{kv=65fhb zWNH`G^Loqv*#q-Q`=NJ_Ad#01`Vmg%4gbc3j$Vy`8o7rJ19~{vN=z~CGJRwmD=4n_ zD-LnlvCcbk$Y5^@^z_&Sc-(`lF~0{9mAA-&20M5vHjXYarDlcz``D<7sF0HJZS(6$ zel!cL4(f+b+3tc3C#pRTkG7e$2i? z*P%XGIf1zNBzQKbSps0g&vXfZ9MnAu$cO17$Gh%19_f6X%Qo>KmrT@@ZIQmwY3ko| z7a`9JbrMq6$C(CoaSb{8Eo~;{?sZ5@9~Tlvhgk!cI9V?Spweml4H%GPmp57tbB|~A z&d6$!aQv5@7zVr_f12n>AVNV4Ygi!^Qv6n1H>~K8(Eel|T)5MraCzq#!zJCmdWc^`21qTeaZg={s z&Zc}%XAJV$&g*go-lNH=>1qv-gZ7mj{8vUvq6e?D?kKu3=yKxHS25FN$aOfpp_fuv zuMw|D_ex-q@lZpTQ`NMFPv?9}|HIL=l*{bcziBLQ-Sw^6YlyelLc~K1pMYY879$qt z%i0MMZklc9-MpkR}T&%NiUt9SQn^ zIXWRD<2P2-77p(-p4-u5Vm3aEAJaO6#TBRt>1c8L;qrlzKUsOv4^7c45d#AQCt$jr ztKe3m?8?3H9&BH$Ehng>0RWMk7L?5nU9$zqOM~_3im~xYrSOurtKHWY9Q zY(LF@%yNz?__n*1U>>?tH(yoIX}3qO)Y?C-79$@2U*Y-voVUP5-x2$mm7O&JD2p%| zOEP&rzd#bQFyY}X9iFhdlJL+WM&7CYVqk>As?wtff+lL@lqz0`Ie<7vMoFud2%iic zDx(gvs%l60nuStTcaR}Q)`fUK0hLT|5=y{F)p4*v(Ue(O;@oZgbP0lcK%84rD47Rx z@|;tXLY*@U@x!(3^iaL|sGmym)^PLb5xdhuseDP95#i${PekQ}l`E=Kc%o7wnjjvp zhfspBhsZxh9${BuJ;h)3O|P!2GYIxf$Szc4|YueU(c78L+ zqjBohm{0105r!1oA~f@aXH-y_UO2v<)Xdrvt9JTy~M4 zLXOC6?%*Uc8xhgK7%}no|H5zW?)Ex}pJgal>dkgtEteM-qn~*CR44#NkrphX0>d-= z;m)a$u8jQu2vbbLO4x*#h<5wi({a}ZJLc3>#J;%1O%xSaQ!;GG8K@EILaKU;?O0k& z&0BN>TbF%;ABV=N&6WEb4o_WAiw)zmfp1;>f_GC&L;3tgR^$tC$8owiC&g^ecZ23D2Ub3$sVEy-v* zr1L+Cd4K96Ys=}e?V;{1#^4I4D&c5q`6$a0HBwV`R#dmLHI@qr38N*jF0uxk*QaVU z-gb6%IkxTbZGq=dl2j2@Bhas+-HTK}_ACb_g=V9_k=+G|^Q8|8d zO>xW=O0Cv25>|19p6D_D!4USi7Brug-@aoUTfE9@e7fX^nM4l%3X$HkzK!oBt#vl1 z>5M32rhBk%X>@kd$7K@NFqtiD2j%sf-(y`^ZB+x!E#`>94+W@2F}h&U3Y)Oc9_)&l zx=)IDSj`Kw_mX1+Y32NeNq7txDZ?6LrS0^>Q-_TjlZ_f^G*2ZAg^HppR34qCRMNg) zLbR{B3>K?V_fh-_otIMbzW+rzNq)nAwGxlt_2xuJr8eilkElAy*mBhD8zx znvG`kO0)obkJccK%yB8hv>>w3O$ytZ0veoH_LKIPr zEtRKd$^BVisL)8<2aG(SD>XA!sG*YbFcBR!l1#y7Tx+#+4-;dwNrMApL1Cr*F(dtU ztftyaBNXz9K#7Ms3d(Aiz|~=yUDa@hAK#vIxb#Alq-^2f%yJp~+yjO|e6_wMOa6+! zYcBkWKse;cN!vAbyy`u+mvnf^T0~V_7y9!q1fm4q_&4};3kVj~2_COss?*=-sfTjD zmmCWY$gE~B#P6##~LawYLIK*JS_r9icViw zVCY?1U5@BEsIw5dWiIeJy6J5e^qp%kM8vxRT-roUN7MPc>>UTq`W^#pse`rnkY#DK z`Z9=k`87RwD^XMQZe$6lkW(3q>yhtcZX|=1j*Dc{nN7W#Xcpn)?l%jts@cD}a-i+7 z$*R5GTCn57qROs;f%m`R@JT$Q-(RwkLnvwJ+O7)M%@cJy+%)?>pOkUMKv9>rFZJPy z4rT$*hX>Qmog1$|5K09~X>OA$LK1(Fxvhhu!`b&bg2+hVO0c^=d>wA&Q@)CB#Hu+# z5@eiox@Xm4TB9uV1P;)=mv7=KW9uxa1s@Ag?bXYw*$?BEHf@O8g}WuKqc`C;4iDRZ zzuW>Q4?!sIYBe3uqOV@oS1oVx)=QhI51ke?0cUXw{(1U$C_x!vlKZ@>$k7pELe>q8 zLHyE@HrCPA4I%wHXLuPG0f552ZetuheZMKou2AjFh{c_%qQ6-jzJ2DXGl49~ggJuI zCPCW^x@c`d)}IT$$gG<4vA!mh_>Lk ztS-L4_o_ptX71~>h_9UvHm(3|mEYN&z-|Ui_kD(YmKQ;qMFq)KCfm~mAJN&}>~fGg z2L^WY*@1g4{zY&8iRcujOobficX!cp>R%-I|LAZc zrc|oP!!DsNQo;=M%VyC*wj?UEd-pH!9j-cSKT;>Y3-+&F> Q|F-)`ipq)93K<0b5B{THQvd(} literal 0 HcmV?d00001 diff --git a/apps/quick-dapp/src/components/ContractGUI/index.tsx b/apps/quick-dapp/src/components/ContractGUI/index.tsx new file mode 100644 index 0000000000..0976531c9e --- /dev/null +++ b/apps/quick-dapp/src/components/ContractGUI/index.tsx @@ -0,0 +1,128 @@ +import React, { useEffect, useState } from 'react'; +import { execution } from '@remix-project/remix-lib'; +import { saveDetails, saveTitle } from '../../actions'; + +const txHelper = execution.txHelper; + +const getFuncABIInputs = (funABI: any) => { + if (!funABI.inputs) { + return ''; + } + return txHelper.inputParametersDeclarationToString(funABI.inputs); +}; + +export function ContractGUI(props: { funcABI: any }) { + const isConstant = + props.funcABI.constant !== undefined ? props.funcABI.constant : false; + const lookupOnly = + props.funcABI.stateMutability === 'view' || + props.funcABI.stateMutability === 'pure' || + isConstant; + const inputs = getFuncABIInputs(props.funcABI); + const [title, setTitle] = useState(''); + const [buttonOptions, setButtonOptions] = useState<{ + title: string; + content: string; + classList: string; + dataId: string; + }>({ title: '', content: '', classList: '', dataId: '' }); + + useEffect(() => { + if (props.funcABI.name) { + setTitle(props.funcABI.name); + } else { + setTitle(props.funcABI.type === 'receive' ? '(receive)' : '(fallback)'); + } + }, [props.funcABI]); + + useEffect(() => { + if (lookupOnly) { + setButtonOptions({ + title: title + ' - call', + content: 'call', + classList: 'btn-info', + dataId: title + ' - call', + }); + } else if ( + props.funcABI.stateMutability === 'payable' || + props.funcABI.payable + ) { + setButtonOptions({ + title: title + ' - transact (payable)', + content: 'transact', + classList: 'btn-danger', + dataId: title + ' - transact (payable)', + }); + } else { + setButtonOptions({ + title: title + ' - transact (not payable)', + content: 'transact', + classList: 'btn-warning', + dataId: title + ' - transact (not payable)', + }); + } + }, [lookupOnly, props.funcABI, title]); + + return ( +
+
+ { + saveTitle({ id: props.funcABI.id, title: value }); + }} + /> +
+
+
+ +
+ 0 + ) + ? 'hidden' + : 'visible', + }} + /> +
+
+