add basicInjectedProvider

pull/3356/head
yann300 2 years ago
parent 140d8a394d
commit d7619601f6
  1. 7
      apps/remix-ide/src/app.js
  2. 18
      apps/remix-ide/src/app/tabs/basic-injected-provider.tsx
  3. 2
      apps/remix-ide/src/app/tabs/external-http-provider.tsx
  4. 2
      apps/remix-ide/src/app/tabs/foundry-provider.tsx
  5. 6
      apps/remix-ide/src/app/tabs/ganache-provider.tsx
  6. 6
      apps/remix-ide/src/app/tabs/hardhat-provider.tsx
  7. 54
      apps/remix-ide/src/app/tabs/injected-L2-provider.tsx
  8. 11
      apps/remix-ide/src/app/tabs/injected-arbitrum-one-provider.tsx
  9. 11
      apps/remix-ide/src/app/tabs/injected-optimism-provider.tsx
  10. 61
      apps/remix-ide/src/app/tabs/injected-provider.tsx
  11. 6
      apps/remix-ide/src/app/udapp/run-tab.js
  12. 51
      apps/remix-ide/src/blockchain/execution-context.js
  13. 4
      apps/remix-ide/src/remixAppManager.js
  14. 9
      libs/remix-ui/run-tab/src/lib/reducers/runTab.ts

@ -31,6 +31,7 @@ import { HardhatProvider } from './app/tabs/hardhat-provider'
import { GanacheProvider } from './app/tabs/ganache-provider'
import { FoundryProvider } from './app/tabs/foundry-provider'
import { ExternalHttpProvider } from './app/tabs/external-http-provider'
import { BasicInjectedProvider } from './app/tabs/basic-injected-provider'
import { Injected0ptimismProvider } from './app/tabs/injected-optimism-provider'
import { InjectedArbitrumOneProvider } from './app/tabs/injected-arbitrum-one-provider'
import { FileDecorator } from './app/plugins/file-decorator'
@ -205,8 +206,9 @@ class AppComponent {
const ganacheProvider = new GanacheProvider(blockchain)
const foundryProvider = new FoundryProvider(blockchain)
const externalHttpProvider = new ExternalHttpProvider(blockchain)
const injected0ptimismProvider = new Injected0ptimismProvider(blockchain)
const injectedArbitrumOneProvider = new InjectedArbitrumOneProvider(blockchain)
const basicInjectedProvider = new BasicInjectedProvider()
const injected0ptimismProvider = new Injected0ptimismProvider()
const injectedArbitrumOneProvider = new InjectedArbitrumOneProvider()
// ----------------- convert offset to line/column service -----------
const offsetToLineColumnConverter = new OffsetToLineColumnConverter()
Registry.getInstance().put({
@ -270,6 +272,7 @@ class AppComponent {
ganacheProvider,
foundryProvider,
externalHttpProvider,
basicInjectedProvider,
injected0ptimismProvider,
injectedArbitrumOneProvider,
this.walkthroughService,

@ -0,0 +1,18 @@
import * as packageJson from '../../../../../package.json'
import { InjectedProvider } from './injected-provider'
const profile = {
name: 'injected',
displayName: 'Injected Provider',
kind: 'provider',
description: 'injected Provider',
methods: ['sendAsync', 'init'],
version: packageJson.version
}
export class BasicInjectedProvider extends InjectedProvider {
constructor () {
super(profile)
}
}

@ -7,7 +7,7 @@ const profile = {
displayName: 'External Http Provider',
kind: 'provider',
description: 'External Http Provider',
methods: ['sendAsync'],
methods: ['sendAsync', 'init'],
version: packageJson.version
}

@ -7,7 +7,7 @@ const profile = {
displayName: 'Foundry Provider',
kind: 'provider',
description: 'Foundry Anvil provider',
methods: ['sendAsync'],
methods: ['sendAsync', 'init'],
version: packageJson.version
}

@ -1,9 +1,5 @@
import * as packageJson from '../../../../../package.json'
import { Plugin } from '@remixproject/engine'
import { AppModal, AlertModal, ModalTypes } from '@remix-ui/app'
import React from 'react' // eslint-disable-line
import { Blockchain } from '../../blockchain/blockchain'
import { ethers } from 'ethers'
import { AbstractProvider } from './abstract-provider'
const profile = {
@ -11,7 +7,7 @@ const profile = {
displayName: 'Ganache Provider',
kind: 'provider',
description: 'Truffle Ganache provider',
methods: ['sendAsync'],
methods: ['sendAsync', 'init'],
version: packageJson.version
}

@ -1,9 +1,5 @@
import * as packageJson from '../../../../../package.json'
import { Plugin } from '@remixproject/engine'
import { AppModal, AlertModal, ModalTypes } from '@remix-ui/app'
import React from 'react' // eslint-disable-line
import { Blockchain } from '../../blockchain/blockchain'
import { ethers } from 'ethers'
import { AbstractProvider } from './abstract-provider'
const profile = {
@ -11,7 +7,7 @@ const profile = {
displayName: 'Hardhat Provider',
kind: 'provider',
description: 'Hardhat provider',
methods: ['sendAsync'],
methods: ['sendAsync', 'init'],
version: packageJson.version
}

@ -0,0 +1,54 @@
import { InjectedProvider } from './injected-provider'
export class InjectedL2Provider extends InjectedProvider {
chainName: string
chainId: string
rpcUrls: Array<string>
constructor (profile: any, chainName: string, chainId: string, rpcUrls: Array<string>) {
super(profile)
this.chainName = chainName
this.chainId = chainId
this.rpcUrls = rpcUrls
}
async init () {
await super.init()
if (this.chainName && this.rpcUrls && this.rpcUrls.length > 0) await addL2Network(this.chainName, this.chainId, this.rpcUrls)
else
throw new Error('Cannot add the L2 network to main injected provider')
}
}
export const addL2Network = async (chainName: string, chainId: string, rpcUrls: Array<string>) => {
try {
await (window as any).ethereum.request({
method: 'wallet_switchEthereumChain',
params: [{ chainId: chainId }],
});
} catch (switchError) {
// This error code indicates that the chain has not been added to MetaMask.
if (switchError.code === 4902) {
try {
await (window as any).ethereum.request({
method: 'wallet_addEthereumChain',
params: [
{
chainId: chainId,
chainName: chainName,
rpcUrls: rpcUrls,
},
],
});
await (window as any).ethereum.request({
method: 'wallet_switchEthereumChain',
params: [{ chainId: chainId }],
});
} catch (addError) {
// handle "add" error
}
}
// handle other "switch" errors
}
}

@ -1,21 +1,18 @@
import * as packageJson from '../../../../../package.json'
import { InjectedProvider } from './injected-provider'
import { InjectedL2Provider } from './injected-L2-provider'
const profile = {
name: 'injected-arbitrum-one-provider',
displayName: 'Injected Arbitrum One Provider',
kind: 'provider',
description: 'injected Arbitrum One Provider',
methods: ['sendAsync'],
methods: ['sendAsync', 'init'],
version: packageJson.version
}
export class InjectedArbitrumOneProvider extends InjectedProvider {
export class InjectedArbitrumOneProvider extends InjectedL2Provider {
constructor () {
super(profile)
this.chainName = 'Arbitrum One'
this.chainId = '0xa4b1'
this.rpcUrls = ['https://arb1.arbitrum.io/rpc']
super(profile, 'Arbitrum One', '0xa4b1', ['https://arb1.arbitrum.io/rpc'])
}
}

@ -1,21 +1,18 @@
import * as packageJson from '../../../../../package.json'
import { InjectedProvider } from './injected-provider'
import { InjectedL2Provider } from './injected-L2-provider'
const profile = {
name: 'injected-optimism-provider',
displayName: 'Injected Optimism Provider',
kind: 'provider',
description: 'injected Optimism Provider',
methods: ['sendAsync'],
methods: ['sendAsync', 'init'],
version: packageJson.version
}
export class Injected0ptimismProvider extends InjectedProvider {
export class Injected0ptimismProvider extends InjectedL2Provider {
constructor () {
super(profile)
this.chainName = 'Optimism'
this.chainId = '0xa'
this.rpcUrls = ['https://mainnet.optimism.io']
super(profile, 'Optimism', '0xa', ['https://mainnet.optimism.io'])
}
}

@ -1,13 +1,12 @@
/* global ethereum */
import { Plugin } from '@remixproject/engine'
import { JsonDataRequest, RejectRequest, SuccessRequest } from './abstract-provider'
import { ethers } from 'ethers'
import Web3 from 'web3'
const noInjectedProviderMsg = 'No injected provider found. Make sure your provider (e.g. MetaMask) is active and running (when recently activated you may have to reload the page).'
export class InjectedProvider extends Plugin {
provider: any
chainName: string
chainId: string
rpcUrls: Array<string>
constructor (profile) {
super(profile)
@ -16,6 +15,26 @@ export class InjectedProvider extends Plugin {
}
}
askPermission (throwIfNoInjectedProvider) {
if (typeof (window as any).ethereum !== "undefined" && typeof (window as any).request === "function") {
(window as any).request({ method: "eth_requestAccounts" })
} else if (throwIfNoInjectedProvider) {
throw new Error(noInjectedProviderMsg)
}
}
async init () {
const injectedProvider = (window as any).ethereum
if (injectedProvider === undefined) {
throw new Error(noInjectedProviderMsg)
} else {
if (injectedProvider && injectedProvider._metamask && injectedProvider._metamask.isUnlocked) {
if (!await injectedProvider._metamask.isUnlocked()) throw new Error('Please make sure the injected provider is unlocked (e.g Metamask).')
}
this.askPermission(true)
}
}
sendAsync (data: JsonDataRequest): Promise<any> {
return new Promise((resolve, reject) => {
this.sendAsyncInternal(data, resolve, reject)
@ -32,7 +51,6 @@ export class InjectedProvider extends Plugin {
try {
if ((window as any) && typeof (window as any).ethereum.request === "function") (window as any).ethereum.request({ method: "eth_requestAccounts" });
if (!await (window as any).ethereum._metamask.isUnlocked()) this.call('notification', 'toast', 'Please make sure the injected provider is unlocked (e.g Metamask).')
await addL2Network(this.chainName, this.chainId, this.rpcUrls)
const resultData = await this.provider.currentProvider.send(data.method, data.params)
resolve({ jsonrpc: '2.0', result: resultData.result, id: data.id })
} catch (error) {
@ -40,36 +58,3 @@ export class InjectedProvider extends Plugin {
}
}
}
export const addL2Network = async (chainName: string, chainId: string, rpcUrls: Array<string>) => {
try {
await (window as any).ethereum.request({
method: 'wallet_switchEthereumChain',
params: [{ chainId: chainId }],
});
} catch (switchError) {
// This error code indicates that the chain has not been added to MetaMask.
if (switchError.code === 4902) {
try {
await (window as any).ethereum.request({
method: 'wallet_addEthereumChain',
params: [
{
chainId: chainId,
chainName: chainName,
rpcUrls: rpcUrls,
},
],
});
await (window as any).ethereum.request({
method: 'wallet_switchEthereumChain',
params: [{ chainId: chainId }],
});
} catch (addError) {
// handle "add" error
}
}
// handle other "switch" errors
}
}

@ -124,6 +124,12 @@ export class RunTab extends ViewPlugin {
await addProvider('foundry-provider', 'Foundry Provider', false)
await addProvider('walletconnect', 'Wallet Connect', false)
await addProvider('basic-http-provider', 'External Http Provider', false)
const displayNameInjected = `Injected Provider${(window && window.ethereum && !(window.ethereum.providers && !window.ethereum.selectedProvider)) ?
window.ethereum.isCoinbaseWallet || window.ethereum.selectedProvider?.isCoinbaseWallet ? ' - Coinbase' :
window.ethereum.isBraveWallet || window.ethereum.selectedProvider?.isBraveWallet ? ' - Brave' :
window.ethereum.isMetaMask || window.ethereum.selectedProvider?.isMetaMask ? ' - MetaMask' : '' : ''}`
await addProvider('injected', displayNameInjected, true)
await addProvider('injected-optimism-provider', 'Optimism Provider', true)
await addProvider('injected-arbitrum-one-provider', 'Arbitrum One Provider', true)
}

@ -14,8 +14,6 @@ if (typeof window !== 'undefined' && typeof window.ethereum !== 'undefined') {
web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545'))
}
const noInjectedProviderMsg = 'No injected provider found. Make sure your provider (e.g. MetaMask) is active and running (when recently activated you may have to reload the page).'
/*
trigger contextChanged, web3EndpointChanged
*/
@ -38,19 +36,8 @@ export class ExecutionContext {
init (config) {
if (config.get('settings/always-use-vm')) {
this.executionContext = 'vm'
} else {
this.executionContext = injectedProvider ? 'injected' : 'vm'
if (this.executionContext === 'injected') this.askPermission(false)
}
}
askPermission (throwIfNoInjectedProvider) {
if (typeof ethereum !== "undefined" && typeof ethereum.request === "function") {
ethereum.request({ method: "eth_requestAccounts" })
} else if (throwIfNoInjectedProvider) {
throw new Error(noInjectedProviderMsg)
}
}
}
getProvider () {
return this.executionContext
@ -84,12 +71,6 @@ export class ExecutionContext {
if (!web3.currentProvider) {
return callback('No provider set')
}
if (web3.currentProvider.isConnected && !web3.currentProvider.isConnected()) {
if (web3.currentProvider.isMetaMask) {
this.askPermission(false)
}
return callback('Provider not connected')
}
web3.eth.net.getId((err, id) => {
let name = null
if (err) name = 'Unknown'
@ -152,28 +133,6 @@ export class ExecutionContext {
return cb()
}
if (context === 'injected') {
if (injectedProvider === undefined) {
infoCb(noInjectedProviderMsg)
return cb()
} else {
if (injectedProvider && injectedProvider._metamask && injectedProvider._metamask.isUnlocked) {
if (!await injectedProvider._metamask.isUnlocked()) infoCb('Please make sure the injected provider is unlocked (e.g Metamask).')
}
try {
this.askPermission(true)
} catch (e) {
infoCb(e.message)
return cb()
}
this.executionContext = context
web3.setProvider(injectedProvider)
await this._updateChainContext()
this.event.trigger('contextChanged', ['injected'])
return cb()
}
}
if (this.customNetWorks[context]) {
var network = this.customNetWorks[context]
if (!this.customNetWorks[context].isInjected) {
@ -182,13 +141,7 @@ export class ExecutionContext {
cb()
})
} else {
// injected
try {
this.askPermission(true)
} catch (e) {
infoCb(e.message)
return cb()
}
// injected
this.executionContext = context
web3.setProvider(network.provider)
await this._updateChainContext()

@ -10,7 +10,7 @@ const requiredModules = [ // services + layout views + system views
'fileManager', 'contentImport', 'blockchain', 'web3Provider', 'scriptRunner', 'fetchAndCompile', 'mainPanel', 'hiddenPanel', 'sidePanel', 'menuicons',
'filePanel', 'terminal', 'settings', 'pluginManager', 'tabs', 'udapp', 'dGitProvider', 'solidity', 'solidity-logic', 'gistHandler', 'layout',
'notification', 'permissionhandler', 'walkthrough', 'storage', 'restorebackupzip', 'link-libraries', 'deploy-libraries', 'openzeppelin-proxy',
'hardhat-provider', 'ganache-provider', 'foundry-provider', 'basic-http-provider', 'injected-optimism-provider', 'injected-arbitrum-one-provider',
'hardhat-provider', 'ganache-provider', 'foundry-provider', 'basic-http-provider', 'injected', 'injected-optimism-provider', 'injected-arbitrum-one-provider',
'compileAndRun', 'search', 'recorder', 'fileDecorator', 'codeParser', 'codeFormatter', 'solidityumlgen', 'contractflattener']
// dependentModules shouldn't be manually activated (e.g hardhat is activated by remixd)
@ -26,7 +26,7 @@ export function isNative(name) {
// nativePlugin allows to bypass the permission request
const nativePlugins = ['vyper', 'workshops', 'debugger', 'remixd', 'menuicons', 'solidity', 'solidity-logic', 'solidityStaticAnalysis', 'solidityUnitTesting',
'layout', 'notification', 'hardhat-provider', 'ganache-provider', 'foundry-provider', 'basic-http-provider', 'injected-optimism-provider',
'tabs', 'injected-arbitrum-one-provider']
'tabs', 'injected-arbitrum-one-provider', 'injected']
return nativePlugins.includes(name) || requiredModules.includes(name)
}

@ -133,15 +133,6 @@ export const runTabInitialState: RunTabState = {
value: 'vm-berlin',
fork: 'berlin',
content: 'Remix VM (Berlin)'
}, {
id: 'injected-mode',
dataId: 'settingsInjectedMode',
title: 'Execution environment has been provided by Metamask or similar provider.',
value: 'injected',
content: `Injected Provider${(window && window.ethereum && !(window.ethereum.providers && !window.ethereum.selectedProvider)) ?
window.ethereum.isCoinbaseWallet || window.ethereum.selectedProvider?.isCoinbaseWallet ? ' - Coinbase' :
window.ethereum.isBraveWallet || window.ethereum.selectedProvider?.isBraveWallet ? ' - Brave' :
window.ethereum.isMetaMask || window.ethereum.selectedProvider?.isMetaMask ? ' - MetaMask' : '' : ''}`
}],
isRequesting: false,
isSuccessful: false,

Loading…
Cancel
Save