Merge pull request #178 from ethereum/addPluginProvider

Add plugin provider
yann300-patch-6
Rob 4 years ago committed by GitHub
commit 5f08c8a722
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      apps/remix-ide/src/app.js
  2. 16
      apps/remix-ide/src/app/files/compiler-metadata.js
  3. 6
      apps/remix-ide/src/app/tabs/network-module.js
  4. 2
      apps/remix-ide/src/app/tabs/runTab/contractDropdown.js
  5. 25
      apps/remix-ide/src/app/tabs/runTab/settings.js
  6. 23
      apps/remix-ide/src/app/udapp/run-tab.js
  7. 9
      apps/remix-ide/src/blockchain/blockchain.js
  8. 15
      apps/remix-ide/src/remixAppManager.js
  9. 29
      libs/remix-lib/src/execution/execution-context.js
  10. 4
      libs/remix-lib/src/execution/txRunner.js

@ -233,7 +233,7 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
const workspace = pluginLoader.get() const workspace = pluginLoader.get()
const engine = new Engine(appManager) const engine = new Engine(appManager)
engine.setPluginOption = ({ name, kind }) => { engine.setPluginOption = ({ name, kind }) => {
if (kind === 'provider') return {queueTimeout: 60000 * 4} if (kind === 'provider') return {queueTimeout: 60000 * 2}
if (name === 'LearnEth') return {queueTimeout: 60000} if (name === 'LearnEth') return {queueTimeout: 60000}
return {queueTimeout: 10000} return {queueTimeout: 10000}
} }

@ -97,10 +97,20 @@ class CompilerMetadata extends Plugin {
} }
// TODO: is only called by dropdownLogic and can be moved there // TODO: is only called by dropdownLogic and can be moved there
deployMetadataOf (contractName) { deployMetadataOf (contractName, fileLocation) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
var provider = this.fileManager.currentFileProvider() var provider
var path = this.fileManager.currentPath() 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) { if (provider && path) {
this.blockchain.detectNetwork((err, { id, name } = {}) => { this.blockchain.detectNetwork((err, { id, name } = {}) => {
if (err) { if (err) {

@ -1,5 +1,6 @@
import { Plugin } from '@remixproject/engine' import { Plugin } from '@remixproject/engine'
import * as packageJson from '../../../../../package.json' import * as packageJson from '../../../../../package.json'
import { Web3 } from 'web3'
export const profile = { export const profile = {
name: 'network', name: 'network',
@ -59,8 +60,9 @@ export class NetworkModule extends Plugin {
} }
/** Add a custom network to the list of available networks */ /** Add a custom network to the list of available networks */
addNetwork (customNetwork) { addNetwork (network) { // { name, url }
this.blockchain.addProvider(customNetwork) 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 */ /** Remove a network to the list of availble networks */

@ -249,7 +249,7 @@ class ContractDropdownUI {
let contractMetadata let contractMetadata
try { try {
contractMetadata = await this.runView.call('compilerMetadata', 'deployMetadataOf', selectedContract.name) contractMetadata = await this.runView.call('compilerMetadata', 'deployMetadataOf', selectedContract.name, selectedContract.contract.file)
} catch (error) { } catch (error) {
return statusCb(`creation of ${selectedContract.name} errored: ` + (error.message ? error.message : error)) return statusCb(`creation of ${selectedContract.name} errored: ` + (error.message ? error.message : error))
} }

@ -34,7 +34,7 @@ class SettingsUI {
setInterval(() => { setInterval(() => {
this.updateAccountBalances() this.updateAccountBalances()
}, 10 * 1000) }, 1000)
this.accountListCallId = 0 this.accountListCallId = 0
this.loadedAccounts = {} this.loadedAccounts = {}
@ -145,7 +145,7 @@ class SettingsUI {
setInterval(() => { setInterval(() => {
this.updateNetwork() this.updateNetwork()
}, 5000) }, 1000)
this.el = el this.el = el
@ -156,24 +156,26 @@ class SettingsUI {
setDropdown (selectExEnv) { setDropdown (selectExEnv) {
this.selectExEnv = selectExEnv this.selectExEnv = selectExEnv
this.blockchain.event.register('addProvider', (network) => { const addProvider = (network) => {
selectExEnv.appendChild(yo`<option selectExEnv.appendChild(yo`<option
title="Manually added environment: ${network.url}" title="provider name: ${network.name}"
value="${network.name}" value="${network.name}"
name="executionContext" name="executionContext"
> >
${network.name} ${network.name}
</option>`) </option>`)
addTooltip(`${network.name} [${network.url}] added`) addTooltip(yo`<span><b>${network.name}</b> provider added</span>`)
}) }
this.blockchain.event.register('removeProvider', (name) => { const removeProvider = (name) => {
var env = selectExEnv.querySelector(`option[value="${name}"]`) var env = selectExEnv.querySelector(`option[value="${name}"]`)
if (env) { if (env) {
selectExEnv.removeChild(env) selectExEnv.removeChild(env)
addTooltip(`${name} removed`) addTooltip(yo`<span><b>${name}</b> provider removed</span>`)
} }
}) }
this.blockchain.event.register('addProvider', provider => addProvider(provider))
this.blockchain.event.register('removeProvider', name => removeProvider(name))
selectExEnv.addEventListener('change', (event) => { selectExEnv.addEventListener('change', (event) => {
let context = selectExEnv.options[selectExEnv.selectedIndex].value let context = selectExEnv.options[selectExEnv.selectedIndex].value
@ -241,7 +243,10 @@ class SettingsUI {
this.onPersonalChange() this.onPersonalChange()
} }
break 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}).`
}
} }
} }

@ -201,6 +201,29 @@ export class RunTab extends LibraryPlugin {
this.renderDropdown(this.udappUI, this.fileManager, this.compilersArtefacts, this.config, this.editor, this.logCallback) 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.renderRecorder(this.udappUI, this.fileManager, this.config, this.logCallback)
this.renderRecorderCard() 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() return this.renderContainer()
} }
} }

@ -67,7 +67,8 @@ class Blockchain {
getCurrentProvider () { getCurrentProvider () {
const provider = this.getProvider() 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 */ /** Return the list of accounts */
@ -285,11 +286,11 @@ class Blockchain {
this.resetEnvironment() this.resetEnvironment()
} }
addNetwork (customNetwork) { addProvider (provider) {
this.executionContext.addProvider(customNetwork) this.executionContext.addProvider(provider)
} }
removeNetwork (name) { removeProvider (name) {
this.executionContext.removeProvider(name) this.executionContext.removeProvider(name)
} }

@ -20,7 +20,7 @@ export function canActivate (name) {
export class RemixAppManager extends PluginManager { export class RemixAppManager extends PluginManager {
constructor (plugins) { constructor () {
super() super()
this.event = new EventEmitter() this.event = new EventEmitter()
this.pluginsDirectory = 'https://raw.githubusercontent.com/ethereum/remix-plugins-directory/master/build/metadata.json' 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 () { async registeredPlugins () {
const res = await fetch(this.pluginsDirectory) 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)) return plugins.map(plugin => new IframePlugin(plugin))
} }
} }

@ -174,13 +174,14 @@ function ExecutionContext () {
this.removeProvider = (name) => { this.removeProvider = (name) => {
if (name && this.customNetWorks[name]) { if (name && this.customNetWorks[name]) {
if (executionContext === name) this.setContext('vm', null)
delete this.customNetWorks[name] delete this.customNetWorks[name]
this.event.trigger('removeProvider', [name]) this.event.trigger('removeProvider', [name])
} }
} }
this.addProvider = (network) => { this.addProvider = (network) => {
if (network && network.name && network.url) { if (network && network.name && !this.customNetWorks[network.name]) {
this.customNetWorks[network.name] = network this.customNetWorks[network.name] = network
this.event.trigger('addProvider', [network]) this.event.trigger('addProvider', [network])
} }
@ -205,7 +206,8 @@ function ExecutionContext () {
this.executionContextChange = (context, endPointUrl, confirmCb, infoCb, cb) => { this.executionContextChange = (context, endPointUrl, confirmCb, infoCb, cb) => {
if (!cb) cb = () => {} if (!cb) cb = () => {}
if (!confirmCb) confirmCb = () => {}
if (!infoCb) infoCb = () => {}
if (context === 'vm') { if (context === 'vm') {
executionContext = context executionContext = context
vms[currentFork].stateManager.revert(() => { vms[currentFork].stateManager.revert(() => {
@ -234,8 +236,11 @@ function ExecutionContext () {
} }
if (this.customNetWorks[context]) { if (this.customNetWorks[context]) {
var provider = this.customNetWorks[context] var network = this.customNetWorks[context]
setProviderFromEndpoint(provider.url, 'web3', () => { cb() }) 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 // TODO: remove this when this function is moved
const self = this 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 const oldProvider = web3.currentProvider
if (endpoint === 'ipc') { web3.setProvider(endpoint)
web3.setProvider(new web3.providers.IpcProvider())
} else {
web3.setProvider(new web3.providers.HttpProvider(endpoint))
}
web3.eth.net.isListening((err, isConnected) => { web3.eth.net.isListening((err, isConnected) => {
if (!err && isConnected) { if (!err && isConnected) {
executionContext = context executionContext = context
self._updateBlockGasLimit() self._updateBlockGasLimit()
self.event.trigger('contextChanged', ['web3']) self.event.trigger('contextChanged', [context])
self.event.trigger('web3EndpointChanged') self.event.trigger('web3EndpointChanged')
cb() cb()
} else { } else {
web3.setProvider(oldProvider) 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) => { this.txDetailsLink = (network, hash) => {
if (transactionDetailsLinks[network]) { if (transactionDetailsLinks[network]) {

@ -177,6 +177,10 @@ class TxRunner {
}) })
} }
this.executionContext.web3().eth.estimateGas(tx, (err, gasEstimation) => { 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, () => { gasEstimationForceSend(err, () => {
// callback is called whenever no error // callback is called whenever no error
tx.gas = !gasEstimation ? gasLimit : gasEstimation tx.gas = !gasEstimation ? gasLimit : gasEstimation

Loading…
Cancel
Save