Merge branch 'master' into filedecoratorplugin

pull/5370/head
Aniket 3 years ago committed by GitHub
commit 4b569e72b8
  1. 8
      apps/remix-ide-e2e/nightwatch.ts
  2. 56
      apps/remix-ide-e2e/src/tests/url.test.ts
  3. 36
      libs/remix-core-plugin/src/lib/helpers/fetch-etherscan.ts
  4. 16
      libs/remix-ui/workspace/src/lib/actions/index.ts

@ -29,7 +29,13 @@ module.exports = {
javascriptEnabled: true, javascriptEnabled: true,
acceptSslCerts: true, acceptSslCerts: true,
'goog:chromeOptions': { 'goog:chromeOptions': {
args: ['window-size=2560,1440', 'start-fullscreen', '--no-sandbox', '--headless', '--verbose'] args: ['window-size=2560,1440',
'start-fullscreen',
'--no-sandbox',
'--headless',
'--verbose',
"--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36",
]
} }
} }
}, },

@ -41,6 +41,7 @@ const sources = [
] ]
module.exports = { module.exports = {
'@disabled': true,
before: function (browser: NightwatchBrowser, done: VoidFunction) { before: function (browser: NightwatchBrowser, done: VoidFunction) {
init(browser, done, 'http://127.0.0.1:8080/#optimize=true&runs=300&evmVersion=istanbul&version=soljson-v0.7.4+commit.3f05b770.js', true) init(browser, done, 'http://127.0.0.1:8080/#optimize=true&runs=300&evmVersion=istanbul&version=soljson-v0.7.4+commit.3f05b770.js', true)
}, },
@ -49,7 +50,7 @@ module.exports = {
return sources return sources
}, },
'Should load the code from URL params (code param)': function (browser: NightwatchBrowser) { 'Should load the code from URL params (code param) #group1': function (browser: NightwatchBrowser) {
browser browser
.waitForElementVisible('[for="autoCompile"]') .waitForElementVisible('[for="autoCompile"]')
.click('[for="autoCompile"]') // we set it too false in the local storage .click('[for="autoCompile"]') // we set it too false in the local storage
@ -66,11 +67,11 @@ module.exports = {
.getEditorValue((content) => { .getEditorValue((content) => {
browser.assert.ok(content && content.indexOf( browser.assert.ok(content && content.indexOf(
'https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/Ownable.sol') !== -1, 'https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/Ownable.sol') !== -1,
'code has not been loaded') 'code has not been loaded')
}) })
}, },
'Should load the code from URL params (url param)': function (browser: NightwatchBrowser) { 'Should load the code from URL params (url param) #group1': function (browser: NightwatchBrowser) {
browser browser
.pause(5000) .pause(5000)
.url('http://127.0.0.1:8080/#optimize=true&runs=300&evmVersion=istanbul&version=soljson-v0.7.4+commit.3f05b770.js&url=https://github.com/ethereum/remix-project/blob/master/apps/remix-ide/contracts/app/solidity/mode.sol') .url('http://127.0.0.1:8080/#optimize=true&runs=300&evmVersion=istanbul&version=soljson-v0.7.4+commit.3f05b770.js&url=https://github.com/ethereum/remix-project/blob/master/apps/remix-ide/contracts/app/solidity/mode.sol')
@ -80,11 +81,40 @@ module.exports = {
.getEditorValue((content) => { .getEditorValue((content) => {
browser.assert.ok(content && content.indexOf( browser.assert.ok(content && content.indexOf(
'proposals.length = _numProposals;') !== -1, 'proposals.length = _numProposals;') !== -1,
'url has not been loaded') 'url has not been loaded')
}) })
}, },
'Should load the code from URL & code params': function (browser: NightwatchBrowser) { 'Should load Etherscan verified contractss from URL "address" param) #group2': function (browser: NightwatchBrowser) {
browser
.pause(5000)
.url('http://127.0.0.1:8080/#address=0x56db08fb78bc6689a1ef66efd079083fed0e4915')
.refresh()
.pause(7000)
.currentWorkspaceIs('etherscan-code-sample')
.assert.elementPresent('*[data-id=treeViewLitreeViewItemropsten]')
.assert.elementPresent('*[data-id=treeViewLitreeViewItemrinkeby]')
.assert.elementPresent('*[data-id="treeViewLitreeViewItemrinkeby/0x56db08fb78bc6689a1ef66efd079083fed0e4915"]')
.assert.elementPresent('*[data-id="treeViewLitreeViewItemrinkeby/0x56db08fb78bc6689a1ef66efd079083fed0e4915/Sample.sol"]')
.getEditorValue((content) => {
browser.assert.ok(content && content.indexOf(
'contract Sample {') !== -1)
})
.url('http://127.0.0.1:8080/#address=0xdac17f958d2ee523a2206206994597c13d831ec7')
.refresh()
.pause(7000)
.currentWorkspaceIs('etherscan-code-sample')
.assert.elementPresent('*[data-id=treeViewLitreeViewItemmainnet]')
.assert.elementPresent('*[data-id="treeViewLitreeViewItemmainnet/0xdac17f958d2ee523a2206206994597c13d831ec7"]')
.assert.elementPresent('*[data-id="treeViewLitreeViewItemmainnet/0xdac17f958d2ee523a2206206994597c13d831ec7/TetherToken.sol"]')
.getEditorValue((content) => {
browser.assert.ok(content && content.indexOf(
'contract TetherToken is Pausable, StandardToken, BlackList {') !== -1)
})
},
'Should load the code from URL & code params #group1': function (browser: NightwatchBrowser) {
browser browser
.pause(5000) .pause(5000)
.url('http://127.0.0.1:8080/#optimize=true&runs=300&evmVersion=istanbul&version=soljson-v0.7.4+commit.3f05b770.js&url=https://github.com/ethereum/remix-project/blob/master/apps/remix-ide/contracts/app/solidity/mode.sol&code=cHJhZ21hIHNvbGlkaXR5ID49MC42LjAgPDAuNy4wOwoKaW1wb3J0ICJodHRwczovL2dpdGh1Yi5jb20vT3BlblplcHBlbGluL29wZW56ZXBwZWxpbi1jb250cmFjdHMvYmxvYi9tYXN0ZXIvY29udHJhY3RzL2FjY2Vzcy9Pd25hYmxlLnNvbCI7Cgpjb250cmFjdCBHZXRQYWlkIGlzIE93bmFibGUgewogIGZ1bmN0aW9uIHdpdGhkcmF3KCkgZXh0ZXJuYWwgb25seU93bmVyIHsKICB9Cn0') .url('http://127.0.0.1:8080/#optimize=true&runs=300&evmVersion=istanbul&version=soljson-v0.7.4+commit.3f05b770.js&url=https://github.com/ethereum/remix-project/blob/master/apps/remix-ide/contracts/app/solidity/mode.sol&code=cHJhZ21hIHNvbGlkaXR5ID49MC42LjAgPDAuNy4wOwoKaW1wb3J0ICJodHRwczovL2dpdGh1Yi5jb20vT3BlblplcHBlbGluL29wZW56ZXBwZWxpbi1jb250cmFjdHMvYmxvYi9tYXN0ZXIvY29udHJhY3RzL2FjY2Vzcy9Pd25hYmxlLnNvbCI7Cgpjb250cmFjdCBHZXRQYWlkIGlzIE93bmFibGUgewogIGZ1bmN0aW9uIHdpdGhkcmF3KCkgZXh0ZXJuYWwgb25seU93bmVyIHsKICB9Cn0')
@ -95,7 +125,7 @@ module.exports = {
.getEditorValue((content) => { .getEditorValue((content) => {
browser.assert.ok(content && content.indexOf( browser.assert.ok(content && content.indexOf(
'proposals.length = _numProposals;') !== -1, 'proposals.length = _numProposals;') !== -1,
'code has not been loaded') 'code has not been loaded')
}) })
.openFile('contract-76747f6e19.sol') .openFile('contract-76747f6e19.sol')
.openFile('ethereum') .openFile('ethereum')
@ -108,7 +138,7 @@ module.exports = {
.openFile('ethereum/remix-project/apps/remix-ide/contracts/app/solidity/mode.sol') .openFile('ethereum/remix-project/apps/remix-ide/contracts/app/solidity/mode.sol')
}, },
'Should load the code from language & code params': function (browser: NightwatchBrowser) { 'Should load the code from language & code params #group1': function (browser: NightwatchBrowser) {
browser browser
.pause(5000) .pause(5000)
.url('http://127.0.0.1:8080/#language=yul&version=soljson-v0.8.7+commit.e28d00a7.js&code=Ly8gQSBjb250cmFjdCBjb25zaXN0cyBvZiBhIHNpbmdsZSBvYmplY3Qgd2l0aCBzdWItb2JqZWN0cyByZXByZXNlbnRpbmcKLy8gdGhlIGNvZGUgdG8gYmUgZGVwbG95ZWQgb3Igb3RoZXIgY29udHJhY3RzIGl0IGNhbiBjcmVhdGUuCi8vIFRoZSBzaW5nbGUgImNvZGUiIG5vZGUgaXMgdGhlIGV4ZWN1dGFibGUgY29kZSBvZiB0aGUgb2JqZWN0LgovLyBFdmVyeSAob3RoZXIpIG5hbWVkIG9iamVjdCBvciBkYXRhIHNlY3Rpb24gaXMgc2VyaWFsaXplZCBhbmQKLy8gbWFkZSBhY2Nlc3NpYmxlIHRvIHRoZSBzcGVjaWFsIGJ1aWx0LWluIGZ1bmN0aW9ucyBkYXRhY29weSAvIGRhdGFvZmZzZXQgLyBkYXRhc2l6ZQovLyBUaGUgY3VycmVudCBvYmplY3QsIHN1Yi1vYmplY3RzIGFuZCBkYXRhIGl0ZW1zIGluc2lkZSB0aGUgY3VycmVudCBvYmplY3QKLy8gYXJlIGluIHNjb3BlLgpvYmplY3QgIkNvbnRyYWN0MSIgewogICAgLy8gVGhpcyBpcyB0aGUgY29uc3RydWN0b3IgY29kZSBvZiB0aGUgY29udHJhY3QuCiAgICBjb2RlIHsKICAgICAgICBmdW5jdGlvbiBhbGxvY2F0ZShzaXplKSAtPiBwdHIgewogICAgICAgICAgICBwdHIgOj0gbWxvYWQoMHg0MCkKICAgICAgICAgICAgaWYgaXN6ZXJvKHB0cikgeyBwdHIgOj0gMHg2MCB9CiAgICAgICAgICAgIG1zdG9yZSgweDQwLCBhZGQocHRyLCBzaXplKSkKICAgICAgICB9CgogICAgICAgIC8vIGZpcnN0IGNyZWF0ZSAiQ29udHJhY3QyIgogICAgICAgIGxldCBzaXplIDo9IGRhdGFzaXplKCJDb250cmFjdDIiKQogICAgICAgIGxldCBvZmZzZXQgOj0gYWxsb2NhdGUoc2l6ZSkKICAgICAgICAvLyBUaGlzIHdpbGwgdHVybiBpbnRvIGNvZGVjb3B5IGZvciBFVk0KICAgICAgICBkYXRhY29weShvZmZzZXQsIGRhdGFvZmZzZXQoIkNvbnRyYWN0MiIpLCBzaXplKQogICAgICAgIC8vIGNvbnN0cnVjdG9yIHBhcmFtZXRlciBpcyBhIHNpbmdsZSBudW1iZXIgMHgxMjM0CiAgICAgICAgbXN0b3JlKGFkZChvZmZzZXQsIHNpemUpLCAweDEyMzQpCiAgICAgICAgcG9wKGNyZWF0ZShvZmZzZXQsIGFkZChzaXplLCAzMiksIDApKQoKICAgICAgICAvLyBub3cgcmV0dXJuIHRoZSBydW50aW1lIG9iamVjdCAodGhlIGN1cnJlbnRseQogICAgICAgIC8vIGV4ZWN1dGluZyBjb2RlIGlzIHRoZSBjb25zdHJ1Y3RvciBjb2RlKQogICAgICAgIHNpemUgOj0gZGF0YXNpemUoIkNvbnRyYWN0MV9kZXBsb3llZCIpCiAgICAgICAgb2Zmc2V0IDo9IGFsbG9jYXRlKHNpemUpCiAgICAgICAgLy8gVGhpcyB3aWxsIHR1cm4gaW50byBhIG1lbW9yeS0+bWVtb3J5IGNvcHkgZm9yIEV3YXNtIGFuZAogICAgICAgIC8vIGEgY29kZWNvcHkgZm9yIEVWTQogICAgICAgIGRhdGFjb3B5KG9mZnNldCwgZGF0YW9mZnNldCgiQ29udHJhY3QxX2RlcGxveWVkIiksIHNpemUpCiAgICAgICAgcmV0dXJuKG9mZnNldCwgc2l6ZSkKICAgIH0KCiAgICBkYXRhICJUYWJsZTIiIGhleCI0MTIzIgoKICAgIG9iamVjdCAiQ29udHJhY3QxX2RlcGxveWVkIiB7CiAgICAgICAgY29kZSB7CiAgICAgICAgICAgIGZ1bmN0aW9uIGFsbG9jYXRlKHNpemUpIC0+IHB0ciB7CiAgICAgICAgICAgICAgICBwdHIgOj0gbWxvYWQoMHg0MCkKICAgICAgICAgICAgICAgIGlmIGlzemVybyhwdHIpIHsgcHRyIDo9IDB4NjAgfQogICAgICAgICAgICAgICAgbXN0b3JlKDB4NDAsIGFkZChwdHIsIHNpemUpKQogICAgICAgICAgICB9CgogICAgICAgICAgICAvLyBydW50aW1lIGNvZGUKCiAgICAgICAgICAgIG1zdG9yZSgwLCAiSGVsbG8sIFdvcmxkISIpCiAgICAgICAgICAgIHJldHVybigwLCAweDIwKQogICAgICAgIH0KICAgIH0KCiAgICAvLyBFbWJlZGRlZCBvYmplY3QuIFVzZSBjYXNlIGlzIHRoYXQgdGhlIG91dHNpZGUgaXMgYSBmYWN0b3J5IGNvbnRyYWN0LAogICAgLy8gYW5kIENvbnRyYWN0MiBpcyB0aGUgY29kZSB0byBiZSBjcmVhdGVkIGJ5IHRoZSBmYWN0b3J5CiAgICBvYmplY3QgIkNvbnRyYWN0MiIgewogICAgICAgIGNvZGUgewogICAgICAgICAgICAvLyBjb2RlIGhlcmUgLi4uCiAgICAgICAgfQoKICAgICAgICBvYmplY3QgIkNvbnRyYWN0Ml9kZXBsb3llZCIgewogICAgICAgICAgICBjb2RlIHsKICAgICAgICAgICAgICAgIC8vIGNvZGUgaGVyZSAuLi4KICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgZGF0YSAiVGFibGUxIiBoZXgiNDEyMyIKICAgIH0KfQ&optimize=false&runs=200&evmVersion=null') .url('http://127.0.0.1:8080/#language=yul&version=soljson-v0.8.7+commit.e28d00a7.js&code=Ly8gQSBjb250cmFjdCBjb25zaXN0cyBvZiBhIHNpbmdsZSBvYmplY3Qgd2l0aCBzdWItb2JqZWN0cyByZXByZXNlbnRpbmcKLy8gdGhlIGNvZGUgdG8gYmUgZGVwbG95ZWQgb3Igb3RoZXIgY29udHJhY3RzIGl0IGNhbiBjcmVhdGUuCi8vIFRoZSBzaW5nbGUgImNvZGUiIG5vZGUgaXMgdGhlIGV4ZWN1dGFibGUgY29kZSBvZiB0aGUgb2JqZWN0LgovLyBFdmVyeSAob3RoZXIpIG5hbWVkIG9iamVjdCBvciBkYXRhIHNlY3Rpb24gaXMgc2VyaWFsaXplZCBhbmQKLy8gbWFkZSBhY2Nlc3NpYmxlIHRvIHRoZSBzcGVjaWFsIGJ1aWx0LWluIGZ1bmN0aW9ucyBkYXRhY29weSAvIGRhdGFvZmZzZXQgLyBkYXRhc2l6ZQovLyBUaGUgY3VycmVudCBvYmplY3QsIHN1Yi1vYmplY3RzIGFuZCBkYXRhIGl0ZW1zIGluc2lkZSB0aGUgY3VycmVudCBvYmplY3QKLy8gYXJlIGluIHNjb3BlLgpvYmplY3QgIkNvbnRyYWN0MSIgewogICAgLy8gVGhpcyBpcyB0aGUgY29uc3RydWN0b3IgY29kZSBvZiB0aGUgY29udHJhY3QuCiAgICBjb2RlIHsKICAgICAgICBmdW5jdGlvbiBhbGxvY2F0ZShzaXplKSAtPiBwdHIgewogICAgICAgICAgICBwdHIgOj0gbWxvYWQoMHg0MCkKICAgICAgICAgICAgaWYgaXN6ZXJvKHB0cikgeyBwdHIgOj0gMHg2MCB9CiAgICAgICAgICAgIG1zdG9yZSgweDQwLCBhZGQocHRyLCBzaXplKSkKICAgICAgICB9CgogICAgICAgIC8vIGZpcnN0IGNyZWF0ZSAiQ29udHJhY3QyIgogICAgICAgIGxldCBzaXplIDo9IGRhdGFzaXplKCJDb250cmFjdDIiKQogICAgICAgIGxldCBvZmZzZXQgOj0gYWxsb2NhdGUoc2l6ZSkKICAgICAgICAvLyBUaGlzIHdpbGwgdHVybiBpbnRvIGNvZGVjb3B5IGZvciBFVk0KICAgICAgICBkYXRhY29weShvZmZzZXQsIGRhdGFvZmZzZXQoIkNvbnRyYWN0MiIpLCBzaXplKQogICAgICAgIC8vIGNvbnN0cnVjdG9yIHBhcmFtZXRlciBpcyBhIHNpbmdsZSBudW1iZXIgMHgxMjM0CiAgICAgICAgbXN0b3JlKGFkZChvZmZzZXQsIHNpemUpLCAweDEyMzQpCiAgICAgICAgcG9wKGNyZWF0ZShvZmZzZXQsIGFkZChzaXplLCAzMiksIDApKQoKICAgICAgICAvLyBub3cgcmV0dXJuIHRoZSBydW50aW1lIG9iamVjdCAodGhlIGN1cnJlbnRseQogICAgICAgIC8vIGV4ZWN1dGluZyBjb2RlIGlzIHRoZSBjb25zdHJ1Y3RvciBjb2RlKQogICAgICAgIHNpemUgOj0gZGF0YXNpemUoIkNvbnRyYWN0MV9kZXBsb3llZCIpCiAgICAgICAgb2Zmc2V0IDo9IGFsbG9jYXRlKHNpemUpCiAgICAgICAgLy8gVGhpcyB3aWxsIHR1cm4gaW50byBhIG1lbW9yeS0+bWVtb3J5IGNvcHkgZm9yIEV3YXNtIGFuZAogICAgICAgIC8vIGEgY29kZWNvcHkgZm9yIEVWTQogICAgICAgIGRhdGFjb3B5KG9mZnNldCwgZGF0YW9mZnNldCgiQ29udHJhY3QxX2RlcGxveWVkIiksIHNpemUpCiAgICAgICAgcmV0dXJuKG9mZnNldCwgc2l6ZSkKICAgIH0KCiAgICBkYXRhICJUYWJsZTIiIGhleCI0MTIzIgoKICAgIG9iamVjdCAiQ29udHJhY3QxX2RlcGxveWVkIiB7CiAgICAgICAgY29kZSB7CiAgICAgICAgICAgIGZ1bmN0aW9uIGFsbG9jYXRlKHNpemUpIC0+IHB0ciB7CiAgICAgICAgICAgICAgICBwdHIgOj0gbWxvYWQoMHg0MCkKICAgICAgICAgICAgICAgIGlmIGlzemVybyhwdHIpIHsgcHRyIDo9IDB4NjAgfQogICAgICAgICAgICAgICAgbXN0b3JlKDB4NDAsIGFkZChwdHIsIHNpemUpKQogICAgICAgICAgICB9CgogICAgICAgICAgICAvLyBydW50aW1lIGNvZGUKCiAgICAgICAgICAgIG1zdG9yZSgwLCAiSGVsbG8sIFdvcmxkISIpCiAgICAgICAgICAgIHJldHVybigwLCAweDIwKQogICAgICAgIH0KICAgIH0KCiAgICAvLyBFbWJlZGRlZCBvYmplY3QuIFVzZSBjYXNlIGlzIHRoYXQgdGhlIG91dHNpZGUgaXMgYSBmYWN0b3J5IGNvbnRyYWN0LAogICAgLy8gYW5kIENvbnRyYWN0MiBpcyB0aGUgY29kZSB0byBiZSBjcmVhdGVkIGJ5IHRoZSBmYWN0b3J5CiAgICBvYmplY3QgIkNvbnRyYWN0MiIgewogICAgICAgIGNvZGUgewogICAgICAgICAgICAvLyBjb2RlIGhlcmUgLi4uCiAgICAgICAgfQoKICAgICAgICBvYmplY3QgIkNvbnRyYWN0Ml9kZXBsb3llZCIgewogICAgICAgICAgICBjb2RlIHsKICAgICAgICAgICAgICAgIC8vIGNvZGUgaGVyZSAuLi4KICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgZGF0YSAiVGFibGUxIiBoZXgiNDEyMyIKICAgIH0KfQ&optimize=false&runs=200&evmVersion=null')
@ -124,7 +154,7 @@ module.exports = {
}) })
}, },
'Should select deploy with proxy option from URL params': function (browser: NightwatchBrowser) { 'Should select deploy with proxy option from URL params #group1': function (browser: NightwatchBrowser) {
browser browser
.url('http://127.0.0.1:8080/#optimize=false&runs=200&deployProxy=true') .url('http://127.0.0.1:8080/#optimize=false&runs=200&deployProxy=true')
.refresh() .refresh()
@ -142,7 +172,7 @@ module.exports = {
.expect.element('[data-id="contractGUIDeployWithProxy"]').to.be.selected .expect.element('[data-id="contractGUIDeployWithProxy"]').to.be.selected
}, },
'Should select upgrade with proxy option from URL params': function (browser: NightwatchBrowser) { 'Should select upgrade with proxy option from URL params #group1': function (browser: NightwatchBrowser) {
browser browser
.url('http://127.0.0.1:8080/#optimize=false&runs=200&upgradeProxy=true') .url('http://127.0.0.1:8080/#optimize=false&runs=200&upgradeProxy=true')
.refresh() .refresh()
@ -159,7 +189,7 @@ module.exports = {
.expect.element('[data-id="contractGUIUpgradeImplementation"]').to.be.selected .expect.element('[data-id="contractGUIUpgradeImplementation"]').to.be.selected
}, },
'Should load using various URL compiler params': function (browser: NightwatchBrowser) { 'Should load using various URL compiler params #group1': function (browser: NightwatchBrowser) {
browser browser
.pause(5000) .pause(5000)
.url('http://127.0.0.1:8080/#optimize=true&runs=300&autoCompile=true&evmVersion=istanbul&version=soljson-v0.7.4+commit.3f05b770.js&language=Yul') .url('http://127.0.0.1:8080/#optimize=true&runs=300&autoCompile=true&evmVersion=istanbul&version=soljson-v0.7.4+commit.3f05b770.js&language=Yul')
@ -185,7 +215,7 @@ module.exports = {
.assert.containsText('#versionSelector option[data-id="selected"]', '0.8.15+commit.e14f2714') .assert.containsText('#versionSelector option[data-id="selected"]', '0.8.15+commit.e14f2714')
}, },
'Should load using compiler from link passed in remix URL': function (browser: NightwatchBrowser) { 'Should load using compiler from link passed in remix URL #group1': function (browser: NightwatchBrowser) {
browser browser
.url('http://127.0.0.1:8080/#version=https://solidity-blog.s3.eu-central-1.amazonaws.com/data/08preview/soljson.js&optimize=false') .url('http://127.0.0.1:8080/#version=https://solidity-blog.s3.eu-central-1.amazonaws.com/data/08preview/soljson.js&optimize=false')
.refresh() .refresh()
@ -194,7 +224,7 @@ module.exports = {
.pause(5000) .pause(5000)
.click('*[data-id="scConfigExpander"]') .click('*[data-id="scConfigExpander"]')
.assert.containsText('#versionSelector option[data-id="selected"]', 'custom') .assert.containsText('#versionSelector option[data-id="selected"]', 'custom')
// default values // default values
.assert.containsText('#evmVersionSelector option[data-id="selected"]', 'default') .assert.containsText('#evmVersionSelector option[data-id="selected"]', 'default')
.verify.elementPresent('#optimize') .verify.elementPresent('#optimize')
.assert.elementNotPresent('#optimize:checked') .assert.elementNotPresent('#optimize:checked')
@ -203,7 +233,7 @@ module.exports = {
.verify.attributeEquals('#runs', 'value', '200') .verify.attributeEquals('#runs', 'value', '200')
}, },
'Should load json files from link passed in remix URL': function (browser: NightwatchBrowser) { 'Should load json files from link passed in remix URL #group1': function (browser: NightwatchBrowser) {
browser browser
.url('http://127.0.0.1:8080/#optimize=false&runs=200&evmVersion=null&version=soljson-v0.6.12+commit.27d51765.js&url=https://raw.githubusercontent.com/EthVM/evm-source-verification/main/contracts/1/0x011e5846975c6463a8c6337eecf3cbf64e328884/input.json') .url('http://127.0.0.1:8080/#optimize=false&runs=200&evmVersion=null&version=soljson-v0.6.12+commit.27d51765.js&url=https://raw.githubusercontent.com/EthVM/evm-source-verification/main/contracts/1/0x011e5846975c6463a8c6337eecf3cbf64e328884/input.json')
.refresh() .refresh()

@ -1,24 +1,28 @@
export const fetchContractFromEtherscan = async (plugin, network, contractAddress, targetPath, key?) => { export const fetchContractFromEtherscan = async (plugin, network, contractAddress, targetPath, shouldSetFile = true, key?) => {
let data let data
const compilationTargets = {} const compilationTargets = {}
let etherscanKey let etherscanKey
if (!key) etherscanKey = await plugin.call('config', 'getAppParameter', 'etherscan-access-token') if (!key) etherscanKey = await plugin.call('config', 'getAppParameter', 'etherscan-access-token')
else etherscanKey = key else etherscanKey = key
if (etherscanKey) { if (etherscanKey) {
const endpoint = network.id == 1 ? 'api.etherscan.io' : 'api-' + network.name + '.etherscan.io' const endpoint = network.id == 1 ? 'api.etherscan.io' : 'api-' + network.name + '.etherscan.io'
data = await fetch('https://' + endpoint + '/api?module=contract&action=getsourcecode&address=' + contractAddress + '&apikey=' + etherscanKey) try {
data = await data.json() data = await fetch('https://' + endpoint + '/api?module=contract&action=getsourcecode&address=' + contractAddress + '&apikey=' + etherscanKey)
// etherscan api doc https://docs.etherscan.io/api-endpoints/contracts data = await data.json()
if (data.message === 'OK' && data.status === "1") { // etherscan api doc https://docs.etherscan.io/api-endpoints/contracts
if (data.result.length) { if (data.message === 'OK' && data.status === "1") {
if (data.result[0].SourceCode === '') throw new Error(`contract not verified on Etherscan ${network.name} network`) if (data.result.length) {
if (data.result[0].SourceCode.startsWith('{')) { if (data.result[0].SourceCode === '') throw new Error(`contract not verified on Etherscan ${network.name} network`)
data.result[0].SourceCode = JSON.parse(data.result[0].SourceCode.replace(/(?:\r\n|\r|\n)/g, '').replace(/^{{/,'{').replace(/}}$/,'}')) if (data.result[0].SourceCode.startsWith('{')) {
data.result[0].SourceCode = JSON.parse(data.result[0].SourceCode.replace(/(?:\r\n|\r|\n)/g, '').replace(/^{{/, '{').replace(/}}$/, '}'))
}
} }
} } else throw new Error('unable to retrieve contract data ' + data.message)
} else throw new Error('unable to retrieve contract data ' + data.message) } catch (e) {
throw new Error('unable to retrieve contract data: ' + e.message)
}
} else throw new Error('unable to try fetching the source code from etherscan: etherscan access token not found. please go to the Remix settings page and provide an access token.') } else throw new Error('unable to try fetching the source code from etherscan: etherscan access token not found. please go to the Remix settings page and provide an access token.')
if (!data || !data.result) { if (!data || !data.result) {
@ -27,7 +31,7 @@ export const fetchContractFromEtherscan = async (plugin, network, contractAddres
if (typeof data.result[0].SourceCode === 'string') { if (typeof data.result[0].SourceCode === 'string') {
const fileName = `${targetPath}/${data.result[0].ContractName}.sol` const fileName = `${targetPath}/${data.result[0].ContractName}.sol`
await plugin.call('fileManager', 'setFile', fileName , data.result[0].SourceCode) if (shouldSetFile) await plugin.call('fileManager', 'setFile', fileName, data.result[0].SourceCode)
compilationTargets[fileName] = { content: data.result[0].SourceCode } compilationTargets[fileName] = { content: data.result[0].SourceCode }
} else if (data.result[0].SourceCode && typeof data.result[0].SourceCode == 'object') { } else if (data.result[0].SourceCode && typeof data.result[0].SourceCode == 'object') {
const sources = data.result[0].SourceCode.sources const sources = data.result[0].SourceCode.sources
@ -36,10 +40,10 @@ export const fetchContractFromEtherscan = async (plugin, network, contractAddres
file = file.replace(/^\//g, '') // remove first slash. file = file.replace(/^\//g, '') // remove first slash.
if (await plugin.call('contentImport', 'isExternalUrl', file)) { if (await plugin.call('contentImport', 'isExternalUrl', file)) {
// nothing to do, the compiler callback will handle those // nothing to do, the compiler callback will handle those
} else { } else {
const path = `${targetPath}/${file}` const path = `${targetPath}/${file}`
const content = (source as any).content const content = (source as any).content
await plugin.call('fileManager', 'setFile', path, content) if (shouldSetFile) await plugin.call('fileManager', 'setFile', path, content)
compilationTargets[path] = { content } compilationTargets[path] = { content }
} }
} }
@ -47,7 +51,7 @@ export const fetchContractFromEtherscan = async (plugin, network, contractAddres
let runs = 0 let runs = 0
try { try {
runs = parseInt(data.result[0].Runs) runs = parseInt(data.result[0].Runs)
} catch (e) {} } catch (e) { }
const settings = { const settings = {
version: data.result[0].CompilerVersion.replace(/^v/, ''), version: data.result[0].CompilerVersion.replace(/^v/, ''),
language: 'Solidity', language: 'Solidity',

@ -4,7 +4,7 @@ import Gists from 'gists'
import { customAction } from '@remixproject/plugin-api/lib/file-system/file-panel/type' import { customAction } from '@remixproject/plugin-api/lib/file-system/file-panel/type'
import { displayNotification, displayPopUp, fetchDirectoryError, fetchDirectoryRequest, fetchDirectorySuccess, focusElement, fsInitializationCompleted, hidePopUp, removeInputFieldSuccess, setCurrentWorkspace, setExpandPath, setMode, setWorkspaces } from './payload' import { displayNotification, displayPopUp, fetchDirectoryError, fetchDirectoryRequest, fetchDirectorySuccess, focusElement, fsInitializationCompleted, hidePopUp, removeInputFieldSuccess, setCurrentWorkspace, setExpandPath, setMode, setWorkspaces } from './payload'
import { listenOnPluginEvents, listenOnProviderEvents } from './events' import { listenOnPluginEvents, listenOnProviderEvents } from './events'
import { createWorkspaceTemplate, getWorkspaces, loadWorkspacePreset, setPlugin } from './workspace' import { createWorkspaceTemplate, getWorkspaces, loadWorkspacePreset, setPlugin, workspaceExists } from './workspace'
import { QueryParams } from '@remix-project/remix-lib' import { QueryParams } from '@remix-project/remix-lib'
import { fetchContractFromEtherscan } from '@remix-project/core-plugin' // eslint-disable-line import { fetchContractFromEtherscan } from '@remix-project/core-plugin' // eslint-disable-line
import JSZip from 'jszip' import JSZip from 'jszip'
@ -80,11 +80,13 @@ export const initWorkspace = (filePanelPlugin) => async (reducerDispatch: React.
{id: 5, name: 'goerli'} {id: 5, name: 'goerli'}
] ]
let found = false let found = false
const workspaceName = 'etherscan-code-sample'
let filePath
const foundOnNetworks = [] const foundOnNetworks = []
for (const network of networks) { for (const network of networks) {
const target = `/${network.name}/${contractAddress}` const target = `/${network.name}/${contractAddress}`
try { try {
data = await fetchContractFromEtherscan(plugin, network, contractAddress, target, etherscanKey) data = await fetchContractFromEtherscan(plugin, network, contractAddress, target, false, etherscanKey)
} catch (error) { } catch (error) {
if ((error.message.startsWith('contract not verified on Etherscan') || error.message.startsWith('unable to retrieve contract data')) && network.id !== 5) if ((error.message.startsWith('contract not verified on Etherscan') || error.message.startsWith('unable to retrieve contract data')) && network.id !== 5)
continue continue
@ -95,15 +97,15 @@ export const initWorkspace = (filePanelPlugin) => async (reducerDispatch: React.
} }
found = true found = true
foundOnNetworks.push(network.name) foundOnNetworks.push(network.name)
await createWorkspaceTemplate('etherscan-code-sample', 'code-template') if (await workspaceExists(workspaceName)) workspaceProvider.setWorkspace(workspaceName)
plugin.setWorkspace({ name: 'etherscan-code-sample', isLocalhost: false }) else await createWorkspaceTemplate(workspaceName, 'code-template')
dispatch(setCurrentWorkspace({ name: 'etherscan-code-sample', isGitRepo: false })) plugin.setWorkspace({ name: workspaceName, isLocalhost: false })
let filePath dispatch(setCurrentWorkspace({ name: workspaceName, isGitRepo: false }))
count = count + (Object.keys(data.compilationTargets)).length count = count + (Object.keys(data.compilationTargets)).length
for (filePath in data.compilationTargets) for (filePath in data.compilationTargets)
await workspaceProvider.set(filePath, data.compilationTargets[filePath]['content']) await workspaceProvider.set(filePath, data.compilationTargets[filePath]['content'])
plugin.on('editor', 'editorMounted', async () => await plugin.fileManager.openFile(filePath))
} }
plugin.on('editor', 'editorMounted', async () => await plugin.fileManager.openFile(filePath))
plugin.call('notification', 'toast', `Added ${count} verified contract${count === 1 ? '': 's'} from ${foundOnNetworks.join(',')} network${foundOnNetworks.length === 1 ? '': 's'} of Etherscan for contract address ${contractAddress} !!`) plugin.call('notification', 'toast', `Added ${count} verified contract${count === 1 ? '': 's'} from ${foundOnNetworks.join(',')} network${foundOnNetworks.length === 1 ? '': 's'} of Etherscan for contract address ${contractAddress} !!`)
} catch (error) { } catch (error) {
await basicWorkspaceInit(workspaces, workspaceProvider) await basicWorkspaceInit(workspaces, workspaceProvider)

Loading…
Cancel
Save