diff --git a/apps/remix-ide/src/app.js b/apps/remix-ide/src/app.js
index 8df7d3601f..8e049113e2 100644
--- a/apps/remix-ide/src/app.js
+++ b/apps/remix-ide/src/app.js
@@ -233,7 +233,7 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
const workspace = pluginLoader.get()
const engine = new Engine(appManager)
engine.setPluginOption = ({ name, kind }) => {
- if (kind === 'provider') return {queueTimeout: 60000 * 4}
+ if (kind === 'provider') return {queueTimeout: 60000 * 2}
if (name === 'LearnEth') return {queueTimeout: 60000}
return {queueTimeout: 10000}
}
diff --git a/apps/remix-ide/src/app/files/compiler-metadata.js b/apps/remix-ide/src/app/files/compiler-metadata.js
index c77bfa7614..68d9293959 100644
--- a/apps/remix-ide/src/app/files/compiler-metadata.js
+++ b/apps/remix-ide/src/app/files/compiler-metadata.js
@@ -97,10 +97,20 @@ class CompilerMetadata extends Plugin {
}
// TODO: is only called by dropdownLogic and can be moved there
- deployMetadataOf (contractName) {
+ deployMetadataOf (contractName, fileLocation) {
return new Promise((resolve, reject) => {
- var provider = this.fileManager.currentFileProvider()
- var path = this.fileManager.currentPath()
+ var provider
+ let path
+ if (fileLocation) {
+ provider = this.fileManager.fileProviderOf(fileLocation)
+ path = fileLocation.split('/')
+ path.pop()
+ path = path.join('/')
+ } else {
+ provider = this.fileManager.currentFileProvider()
+ path = this.fileManager.currentPath()
+ }
+
if (provider && path) {
this.blockchain.detectNetwork((err, { id, name } = {}) => {
if (err) {
diff --git a/apps/remix-ide/src/app/tabs/network-module.js b/apps/remix-ide/src/app/tabs/network-module.js
index cb3e465044..fdae172c15 100644
--- a/apps/remix-ide/src/app/tabs/network-module.js
+++ b/apps/remix-ide/src/app/tabs/network-module.js
@@ -1,5 +1,6 @@
import { Plugin } from '@remixproject/engine'
import * as packageJson from '../../../../../package.json'
+import { Web3 } from 'web3'
export const profile = {
name: 'network',
@@ -59,8 +60,9 @@ export class NetworkModule extends Plugin {
}
/** Add a custom network to the list of available networks */
- addNetwork (customNetwork) {
- this.blockchain.addProvider(customNetwork)
+ addNetwork (network) { // { name, url }
+ const provider = network.url === 'ipc' ? new Web3.providers.IpcProvider() : new Web3.providers.HttpProvider(network.url)
+ this.blockchain.addProvider({ name: network.name, provider })
}
/** Remove a network to the list of availble networks */
diff --git a/apps/remix-ide/src/app/tabs/runTab/contractDropdown.js b/apps/remix-ide/src/app/tabs/runTab/contractDropdown.js
index c69fcd1dd4..76ee2343cf 100644
--- a/apps/remix-ide/src/app/tabs/runTab/contractDropdown.js
+++ b/apps/remix-ide/src/app/tabs/runTab/contractDropdown.js
@@ -249,7 +249,7 @@ class ContractDropdownUI {
let contractMetadata
try {
- contractMetadata = await this.runView.call('compilerMetadata', 'deployMetadataOf', selectedContract.name)
+ contractMetadata = await this.runView.call('compilerMetadata', 'deployMetadataOf', selectedContract.name, selectedContract.contract.file)
} catch (error) {
return statusCb(`creation of ${selectedContract.name} errored: ` + (error.message ? error.message : error))
}
diff --git a/apps/remix-ide/src/app/tabs/runTab/settings.js b/apps/remix-ide/src/app/tabs/runTab/settings.js
index 692828e25e..c49f13a9c8 100644
--- a/apps/remix-ide/src/app/tabs/runTab/settings.js
+++ b/apps/remix-ide/src/app/tabs/runTab/settings.js
@@ -34,7 +34,7 @@ class SettingsUI {
setInterval(() => {
this.updateAccountBalances()
- }, 10 * 1000)
+ }, 1000)
this.accountListCallId = 0
this.loadedAccounts = {}
@@ -145,7 +145,7 @@ class SettingsUI {
setInterval(() => {
this.updateNetwork()
- }, 5000)
+ }, 1000)
this.el = el
@@ -156,24 +156,26 @@ class SettingsUI {
setDropdown (selectExEnv) {
this.selectExEnv = selectExEnv
- this.blockchain.event.register('addProvider', (network) => {
+ const addProvider = (network) => {
selectExEnv.appendChild(yo``)
- addTooltip(`${network.name} [${network.url}] added`)
- })
+ addTooltip(yo`${network.name} provider added`)
+ }
- this.blockchain.event.register('removeProvider', (name) => {
+ const removeProvider = (name) => {
var env = selectExEnv.querySelector(`option[value="${name}"]`)
if (env) {
selectExEnv.removeChild(env)
- addTooltip(`${name} removed`)
+ addTooltip(yo`${name} provider removed`)
}
- })
+ }
+ this.blockchain.event.register('addProvider', provider => addProvider(provider))
+ this.blockchain.event.register('removeProvider', name => removeProvider(name))
selectExEnv.addEventListener('change', (event) => {
let context = selectExEnv.options[selectExEnv.selectedIndex].value
@@ -241,7 +243,10 @@ class SettingsUI {
this.onPersonalChange()
}
break
- default:
+ default: {
+ plusBtn.classList.add(css.disableMouseEvents)
+ plusTitle.title = `Unfortunately it's not possible to create an account using an external wallet (${this.selectExEnv.value}).`
+ }
}
}
diff --git a/apps/remix-ide/src/app/udapp/run-tab.js b/apps/remix-ide/src/app/udapp/run-tab.js
index 4c1978bf87..a12adbb1d8 100644
--- a/apps/remix-ide/src/app/udapp/run-tab.js
+++ b/apps/remix-ide/src/app/udapp/run-tab.js
@@ -201,6 +201,29 @@ export class RunTab extends LibraryPlugin {
this.renderDropdown(this.udappUI, this.fileManager, this.compilersArtefacts, this.config, this.editor, this.logCallback)
this.renderRecorder(this.udappUI, this.fileManager, this.config, this.logCallback)
this.renderRecorderCard()
+
+ const addPluginProvider = (profile) => {
+ if (profile.kind === 'provider') {
+ ((profile, app) => {
+ const web3Provider = {
+ async sendAsync (payload, callback) {
+ try {
+ const result = await app.call(profile.name, 'sendAsync', payload)
+ callback(null, result)
+ } catch (e) {
+ callback(e)
+ }
+ }
+ }
+ app.blockchain.addProvider({ name: profile.displayName, provider: web3Provider })
+ })(profile, this)
+ }
+ }
+ const removePluginProvider = (profile) => {
+ if (profile.kind === 'provider') this.blockchain.removeProvider(profile.displayName)
+ }
+ this.on('manager', 'pluginActivated', addPluginProvider.bind(this))
+ this.on('manager', 'pluginDeactivated', removePluginProvider.bind(this))
return this.renderContainer()
}
}
diff --git a/apps/remix-ide/src/blockchain/blockchain.js b/apps/remix-ide/src/blockchain/blockchain.js
index 5cace4f97d..cf57531072 100644
--- a/apps/remix-ide/src/blockchain/blockchain.js
+++ b/apps/remix-ide/src/blockchain/blockchain.js
@@ -67,7 +67,8 @@ class Blockchain {
getCurrentProvider () {
const provider = this.getProvider()
- return this.providers[provider]
+ if (this.providers[provider]) return this.providers[provider]
+ return this.providers.web3 // default to the common type of provider
}
/** Return the list of accounts */
@@ -285,11 +286,11 @@ class Blockchain {
this.resetEnvironment()
}
- addNetwork (customNetwork) {
- this.executionContext.addProvider(customNetwork)
+ addProvider (provider) {
+ this.executionContext.addProvider(provider)
}
- removeNetwork (name) {
+ removeProvider (name) {
this.executionContext.removeProvider(name)
}
diff --git a/apps/remix-ide/src/remixAppManager.js b/apps/remix-ide/src/remixAppManager.js
index e866bc2641..7e79bcdd35 100644
--- a/apps/remix-ide/src/remixAppManager.js
+++ b/apps/remix-ide/src/remixAppManager.js
@@ -20,7 +20,7 @@ export function canActivate (name) {
export class RemixAppManager extends PluginManager {
- constructor (plugins) {
+ constructor () {
super()
this.event = new EventEmitter()
this.pluginsDirectory = 'https://raw.githubusercontent.com/ethereum/remix-plugins-directory/master/build/metadata.json'
@@ -94,7 +94,18 @@ export class RemixAppManager extends PluginManager {
async registeredPlugins () {
const res = await fetch(this.pluginsDirectory)
- const plugins = await res.json()
+ let plugins = await res.json()
+ plugins.push({
+ 'name': 'walletconnect',
+ 'kind': 'provider',
+ 'displayName': 'Wallet Connect',
+ 'events': [],
+ 'methods': ['sendAsync'],
+ 'url': 'ipfs://QmUD93rF9RKaDabCM5jFTHraBKd72HApbv7m9Vd5i5EHZe',
+ 'description': 'Use an external wallet for transacting',
+ 'icon': 'data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjUxMiIgdmlld0JveD0iMCAwIDUxMiA1MTIiIHdpZHRoPSI1MTIiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPjxyYWRpYWxHcmFkaWVudCBpZD0iYSIgY3g9IjAlIiBjeT0iNTAlIiByPSIxMDAlIj48c3RvcCBvZmZzZXQ9IjAiIHN0b3AtY29sb3I9IiM1ZDlkZjYiLz48c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiMwMDZmZmYiLz48L3JhZGlhbEdyYWRpZW50PjxnIGZpbGw9Im5vbmUiIGZpbGwtcnVsZT0iZXZlbm9kZCI+PHBhdGggZD0ibTI1NiAwYzE0MS4zODQ4OTYgMCAyNTYgMTE0LjYxNTEwNCAyNTYgMjU2cy0xMTQuNjE1MTA0IDI1Ni0yNTYgMjU2LTI1Ni0xMTQuNjE1MTA0LTI1Ni0yNTYgMTE0LjYxNTEwNC0yNTYgMjU2LTI1NnoiIGZpbGw9InVybCgjYSkiLz48cGF0aCBkPSJtNjQuNjkxNzU1OCAzNy43MDg4Mjk4YzUxLjUzMjgwNzItNTAuMjc4NDM5NyAxMzUuMDgzOTk0Mi01MC4yNzg0Mzk3IDE4Ni42MTY3OTkyIDBsNi4yMDIwNTcgNi4wNTEwOTA2YzIuNTc2NjQgMi41MTM5MjE4IDIuNTc2NjQgNi41ODk3OTQ4IDAgOS4xMDM3MTc3bC0yMS4yMTU5OTggMjAuNjk5NTc1OWMtMS4yODgzMjEgMS4yNTY5NjE5LTMuMzc3MSAxLjI1Njk2MTktNC42NjU0MjEgMGwtOC41MzQ3NjYtOC4zMjcwMjA1Yy0zNS45NTA1NzMtMzUuMDc1NDk2Mi05NC4yMzc5NjktMzUuMDc1NDk2Mi0xMzAuMTg4NTQ0IDBsLTkuMTQwMDI4MiA4LjkxNzU1MTljLTEuMjg4MzIxNyAxLjI1Njk2MDktMy4zNzcxMDE2IDEuMjU2OTYwOS00LjY2NTQyMDggMGwtMjEuMjE1OTk3My0yMC42OTk1NzU5Yy0yLjU3NjY0MDMtMi41MTM5MjI5LTIuNTc2NjQwMy02LjU4OTc5NTggMC05LjEwMzcxNzd6bTIzMC40OTM0ODUyIDQyLjgwODkxMTcgMTguODgyMjc5IDE4LjQyMjcyNjJjMi41NzY2MjcgMi41MTM5MTAzIDIuNTc2NjQyIDYuNTg5NzU5My4wMDAwMzIgOS4xMDM2ODYzbC04NS4xNDE0OTggODMuMDcwMzU4Yy0yLjU3NjYyMyAyLjUxMzk0MS02Ljc1NDE4MiAyLjUxMzk2OS05LjMzMDg0LjAwMDA2Ni0uMDAwMDEtLjAwMDAxLS4wMDAwMjMtLjAwMDAyMy0uMDAwMDMzLS4wMDAwMzRsLTYwLjQyODI1Ni01OC45NTc0NTFjLS42NDQxNi0uNjI4NDgxLTEuNjg4NTUtLjYyODQ4MS0yLjMzMjcxIDAtLjAwMDAwNC4wMDAwMDQtLjAwMDAwOC4wMDAwMDctLjAwMDAxMi4wMDAwMTFsLTYwLjQyNjk2ODMgNTguOTU3NDA4Yy0yLjU3NjYxNDEgMi41MTM5NDctNi43NTQxNzQ2IDIuNTEzOTktOS4zMzA4NDA4LjAwMDA5Mi0uMDAwMDE1MS0uMDAwMDE0LS4wMDAwMzA5LS4wMDAwMjktLjAwMDA0NjctLjAwMDA0NmwtODUuMTQzODY3NzQtODMuMDcxNDYzYy0yLjU3NjYzOTI4LTIuNTEzOTIxLTIuNTc2NjM5MjgtNi41ODk3OTUgMC05LjEwMzcxNjNsMTguODgyMzEyNjQtMTguNDIyNjk1NWMyLjU3NjYzOTMtMi41MTM5MjIyIDYuNzU0MTk5My0yLjUxMzkyMjIgOS4zMzA4Mzk3IDBsNjAuNDI5MTM0NyA1OC45NTgyNzU4Yy42NDQxNjA4LjYyODQ4IDEuNjg4NTQ5NS42Mjg0OCAyLjMzMjcxMDMgMCAuMDAwMDA5NS0uMDAwMDA5LjAwMDAxODItLjAwMDAxOC4wMDAwMjc3LS4wMDAwMjVsNjAuNDI2MTA2NS01OC45NTgyNTA4YzIuNTc2NTgxLTIuNTEzOTggNi43NTQxNDItMi41MTQwNzQzIDkuMzMwODQtLjAwMDIxMDMuMDAwMDM3LjAwMDAzNTQuMDAwMDcyLjAwMDA3MDkuMDAwMTA3LjAwMDEwNjNsNjAuNDI5MDU2IDU4Ljk1ODM1NDhjLjY0NDE1OS42Mjg0NzkgMS42ODg1NDkuNjI4NDc5IDIuMzMyNzA5IDBsNjAuNDI4MDc5LTU4Ljk1NzE5MjVjMi41NzY2NC0yLjUxMzkyMzEgNi43NTQxOTktMi41MTM5MjMxIDkuMzMwODM5IDB6IiBmaWxsPSIjZmZmIiBmaWxsLXJ1bGU9Im5vbnplcm8iIHRyYW5zZm9ybT0idHJhbnNsYXRlKDk4IDE2MCkiLz48L2c+PC9zdmc+',
+ 'location': 'mainPanel'
+ })
return plugins.map(plugin => new IframePlugin(plugin))
}
}
diff --git a/libs/remix-lib/src/execution/execution-context.js b/libs/remix-lib/src/execution/execution-context.js
index f1875a209a..4d6829069c 100644
--- a/libs/remix-lib/src/execution/execution-context.js
+++ b/libs/remix-lib/src/execution/execution-context.js
@@ -174,13 +174,14 @@ function ExecutionContext () {
this.removeProvider = (name) => {
if (name && this.customNetWorks[name]) {
+ if (executionContext === name) this.setContext('vm', null)
delete this.customNetWorks[name]
this.event.trigger('removeProvider', [name])
}
}
this.addProvider = (network) => {
- if (network && network.name && network.url) {
+ if (network && network.name && !this.customNetWorks[network.name]) {
this.customNetWorks[network.name] = network
this.event.trigger('addProvider', [network])
}
@@ -205,7 +206,8 @@ function ExecutionContext () {
this.executionContextChange = (context, endPointUrl, confirmCb, infoCb, cb) => {
if (!cb) cb = () => {}
-
+ if (!confirmCb) confirmCb = () => {}
+ if (!infoCb) infoCb = () => {}
if (context === 'vm') {
executionContext = context
vms[currentFork].stateManager.revert(() => {
@@ -234,8 +236,11 @@ function ExecutionContext () {
}
if (this.customNetWorks[context]) {
- var provider = this.customNetWorks[context]
- setProviderFromEndpoint(provider.url, 'web3', () => { cb() })
+ var network = this.customNetWorks[context]
+ this.setProviderFromEndpoint(network.provider, network.name, (error) => {
+ if (error) infoCb(error)
+ cb()
+ })
}
}
@@ -269,29 +274,25 @@ function ExecutionContext () {
// TODO: remove this when this function is moved
const self = this
- // TODO: not used here anymore and needs to be moved
- function setProviderFromEndpoint (endpoint, context, cb) {
+
+ this.setProviderFromEndpoint = (endpoint, context, cb) => {
const oldProvider = web3.currentProvider
- if (endpoint === 'ipc') {
- web3.setProvider(new web3.providers.IpcProvider())
- } else {
- web3.setProvider(new web3.providers.HttpProvider(endpoint))
- }
+ web3.setProvider(endpoint)
+
web3.eth.net.isListening((err, isConnected) => {
if (!err && isConnected) {
executionContext = context
self._updateBlockGasLimit()
- self.event.trigger('contextChanged', ['web3'])
+ self.event.trigger('contextChanged', [context])
self.event.trigger('web3EndpointChanged')
cb()
} else {
web3.setProvider(oldProvider)
- cb('Not possible to connect to the Web3 provider. Make sure the provider is running and a connection is open (via IPC or RPC).')
+ cb('Not possible to connect to the Web3 provider. Make sure the provider is running, a connection is open (via IPC or RPC) or that the provider plugin is properly configured.')
}
})
}
- this.setProviderFromEndpoint = setProviderFromEndpoint
this.txDetailsLink = (network, hash) => {
if (transactionDetailsLinks[network]) {
diff --git a/libs/remix-lib/src/execution/txRunner.js b/libs/remix-lib/src/execution/txRunner.js
index f778ceb388..201136a8b2 100644
--- a/libs/remix-lib/src/execution/txRunner.js
+++ b/libs/remix-lib/src/execution/txRunner.js
@@ -177,6 +177,10 @@ class TxRunner {
})
}
this.executionContext.web3().eth.estimateGas(tx, (err, gasEstimation) => {
+ if (err && err.message.indexOf('Invalid JSON RPC response') !== -1) {
+ // // @todo(#378) this should be removed when https://github.com/WalletConnect/walletconnect-monorepo/issues/334 is fixed
+ err = 'Gas estimation failed because of an unknown internal error. This may indicated that the transaction will fail.'
+ }
gasEstimationForceSend(err, () => {
// callback is called whenever no error
tx.gas = !gasEstimation ? gasLimit : gasEstimation