Merge pull request #3454 from ethereum/trust_wallet_provider

add trustwallet provider
pull/3535/head
yann300 2 years ago committed by GitHub
commit ee31bc06b6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 9
      apps/remix-ide/src/app.js
  2. 18
      apps/remix-ide/src/app/providers/basic-injected-provider.tsx
  3. 4
      apps/remix-ide/src/app/providers/injected-L2-provider.tsx
  4. 40
      apps/remix-ide/src/app/providers/injected-provider-default.tsx
  5. 26
      apps/remix-ide/src/app/providers/injected-provider-trustwallet.tsx
  6. 59
      apps/remix-ide/src/app/providers/injected-provider.tsx
  7. 19
      apps/remix-ide/src/app/udapp/run-tab.js
  8. 8
      apps/remix-ide/src/blockchain/blockchain.js
  9. 2
      apps/remix-ide/src/remixAppManager.js
  10. 6
      libs/remix-ui/run-tab/src/lib/actions/events.ts

@ -36,7 +36,8 @@ import { HardhatProvider } from './app/providers/hardhat-provider'
import { GanacheProvider } from './app/providers/ganache-provider'
import { FoundryProvider } from './app/providers/foundry-provider'
import { ExternalHttpProvider } from './app/providers/external-http-provider'
import { BasicInjectedProvider } from './app/providers/basic-injected-provider'
import { InjectedProviderDefault } from './app/providers/injected-provider-default'
import { InjectedProviderTrustWallet } from './app/providers/injected-provider-trustwallet'
import { Injected0ptimismProvider } from './app/providers/injected-optimism-provider'
import { InjectedArbitrumOneProvider } from './app/providers/injected-arbitrum-one-provider'
import { FileDecorator } from './app/plugins/file-decorator'
@ -216,7 +217,8 @@ class AppComponent {
const ganacheProvider = new GanacheProvider(blockchain)
const foundryProvider = new FoundryProvider(blockchain)
const externalHttpProvider = new ExternalHttpProvider(blockchain)
const basicInjectedProvider = new BasicInjectedProvider()
const trustWalletInjectedProvider = new InjectedProviderTrustWallet()
const defaultInjectedProvider = new InjectedProviderDefault
const injected0ptimismProvider = new Injected0ptimismProvider()
const injectedArbitrumOneProvider = new InjectedArbitrumOneProvider()
// ----------------- convert offset to line/column service -----------
@ -289,7 +291,8 @@ class AppComponent {
ganacheProvider,
foundryProvider,
externalHttpProvider,
basicInjectedProvider,
defaultInjectedProvider,
trustWalletInjectedProvider,
injected0ptimismProvider,
injectedArbitrumOneProvider,
this.walkthroughService,

@ -1,18 +0,0 @@
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)
}
}

@ -1,6 +1,6 @@
import { InjectedProvider } from './injected-provider'
import { InjectedProviderDefaultBase } from './injected-provider-default'
export class InjectedL2Provider extends InjectedProvider {
export class InjectedL2Provider extends InjectedProviderDefaultBase {
chainName: string
chainId: string
rpcUrls: Array<string>

@ -0,0 +1,40 @@
/* global ethereum */
import * as packageJson from '../../../../../package.json'
import { InjectedProvider } from './injected-provider'
export class InjectedProviderDefaultBase extends InjectedProvider {
constructor (profile) {
super(profile)
}
async init () {
const injectedProvider = this.getInjectedProvider()
if (injectedProvider && injectedProvider._metamask && injectedProvider._metamask.isUnlocked) {
if (!await injectedProvider._metamask.isUnlocked()) this.call('notification', 'toast', 'Please make sure the injected provider is unlocked (e.g Metamask).')
}
return super.init()
}
getInjectedProvider () {
return (window as any).ethereum
}
notFound () {
return '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).'
}
}
const profile = {
name: 'injected',
displayName: 'Injected Provider',
kind: 'provider',
description: 'injected Provider',
methods: ['sendAsync', 'init'],
version: packageJson.version
}
export class InjectedProviderDefault extends InjectedProviderDefaultBase {
constructor () {
super(profile)
}
}

@ -0,0 +1,26 @@
/* global ethereum */
import * as packageJson from '../../../../../package.json'
import { InjectedProvider } from './injected-provider'
const profile = {
name: 'injected-trustwallet',
displayName: 'Trust wallet',
kind: 'provider',
description: 'Trust wallet',
methods: ['sendAsync', 'init'],
version: packageJson.version
}
export class InjectedProviderTrustWallet extends InjectedProvider {
constructor () {
super(profile)
}
getInjectedProvider () {
return (window as any).trustwallet
}
notFound () {
return 'Could not find Trust Wallet provider. Please make sure the Trust Wallet extension is active. Download the latest version from https://trustwallet.com/browser-extension'
}
}

@ -2,13 +2,9 @@
import React from 'react' // eslint-disable-line
import { Plugin } from '@remixproject/engine'
import { JsonDataRequest, RejectRequest, SuccessRequest } from '../providers/abstract-provider'
import Web3 from 'web3'
import { IProvider } from './abstract-provider'
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 implements IProvider {
provider: any
export abstract class InjectedProvider extends Plugin implements IProvider {
options: { [id: string] : any } = {}
listenerAccountsChanged: (accounts: Array<string>) => void
listenerChainChanged: (chainId: number) => void
@ -21,26 +17,37 @@ export class InjectedProvider extends Plugin implements IProvider {
this.listenerChainChanged = (chainId: number) => {
this.emit('chainChanged', chainId)
}
if ((window as any).ethereum) {
this.provider = new Web3((window as any).ethereum)
}
}
onActivation(): void {
(window as any).ethereum.on('accountsChanged', this.listenerAccountsChanged);
(window as any).ethereum.on('chainChanged', this.listenerChainChanged);
abstract getInjectedProvider(): any
abstract notFound(): string
onActivation(): void {
try {
const web3Provider = this.getInjectedProvider()
web3Provider.on('accountsChanged', this.listenerAccountsChanged);
web3Provider.on('chainChanged', this.listenerChainChanged);
} catch (error) {
console.log('unable to listen on context changed')
}
}
onDeactivation(): void {
(window as any).ethereum.removeListener('accountsChanged', this.listenerAccountsChanged)
(window as any).ethereum.removeListener('chainChanged', this.listenerChainChanged)
try {
const web3Provider = this.getInjectedProvider()
web3Provider.removeListener('accountsChanged', this.listenerAccountsChanged)
web3Provider.removeListener('chainChanged', this.listenerChainChanged)
} catch (error) {
console.log('unable to remove listener on context changed')
}
}
askPermission (throwIfNoInjectedProvider) {
if ((typeof (window as any).ethereum) !== "undefined" && (typeof (window as any).ethereum.request) === "function") {
(window as any).ethereum.request({ method: "eth_requestAccounts" })
const web3Provider = this.getInjectedProvider()
if (typeof web3Provider !== "undefined" && typeof web3Provider.request === "function") {
web3Provider.request({ method: "eth_requestAccounts" })
} else if (throwIfNoInjectedProvider) {
throw new Error(noInjectedProviderMsg)
throw new Error(this.notFound())
}
}
@ -51,14 +58,11 @@ export class InjectedProvider extends Plugin implements IProvider {
}
async init () {
const injectedProvider = (window as any).ethereum
const injectedProvider = this.getInjectedProvider()
if (injectedProvider === undefined) {
this.call('notification', 'toast', noInjectedProviderMsg)
throw new Error(noInjectedProviderMsg)
this.call('notification', 'toast', this.notFound())
throw new Error(this.notFound())
} else {
if (injectedProvider && injectedProvider._metamask && injectedProvider._metamask.isUnlocked) {
if (!await injectedProvider._metamask.isUnlocked()) this.call('notification', 'toast', 'Please make sure the injected provider is unlocked (e.g Metamask).')
}
this.askPermission(true)
}
return {}
@ -73,12 +77,19 @@ export class InjectedProvider extends Plugin implements IProvider {
private async sendAsyncInternal (data: JsonDataRequest, resolve: SuccessRequest, reject: RejectRequest): Promise<void> {
// Check the case where current environment is VM on UI and it still sends RPC requests
// This will be displayed on UI tooltip as 'cannot get account list: Environment Updated !!'
if (!this.provider) {
const web3Provider = this.getInjectedProvider()
if (!web3Provider) {
this.call('notification', 'toast', 'No injected provider (e.g Metamask) has been found.')
return resolve({ jsonrpc: '2.0', error: 'no injected provider found', id: data.id })
}
try {
let resultData = await this.provider.currentProvider.send(data.method, data.params)
let resultData
if (web3Provider.send) resultData = await web3Provider.send(data.method, data.params)
else if (web3Provider.request) resultData = await web3Provider.request({ method: data.method, params: data.params})
else {
resolve({ jsonrpc: '2.0', error: 'provider not valid', id: data.id })
return
}
if (resultData) {
if (resultData.jsonrpc && resultData.jsonrpc === '2.0') {
resultData = resultData.result

@ -132,11 +132,20 @@ export class RunTab extends ViewPlugin {
}
// basic injected
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, false)
// if it's the trust wallet provider, we have a specific provider for that, see below
if (window && window.ethereum && !(window.ethereum.isTrustWallet || window.ethereum.selectedProvider?.isTrustWallet)) {
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, false)
}
if (window && window.trustwallet) {
const displayNameInjected = `Injected Provider - TrustWallet`
await addProvider('injected-trustwallet', displayNameInjected, true, false)
}
// VM
const titleVM = 'Execution environment is local to Remix. Data is only saved to browser memory and will vanish upon reload.'
await addProvider('vm-merge', 'Remix VM (Merge)', false, true, 'merge', 'settingsVMMergeMode', titleVM)

@ -66,10 +66,18 @@ export class Blockchain extends Plugin {
this._triggerEvent('networkStatus', [this.networkStatus])
})
})
this.on('injected-trustwallet', 'chainChanged', () => {
this.detectNetwork((error, network) => {
this.networkStatus = { network, error }
this._triggerEvent('networkStatus', [this.networkStatus])
})
})
}
onDeactivation () {
this.off('injected', 'chainChanged')
this.off('injected-trustwallet', 'chainChanged')
}
setupEvents () {

@ -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', 'injected-optimism-provider', 'injected-arbitrum-one-provider', 'vm-custom-fork', 'vm-goerli-fork', 'vm-mainnet-fork', 'vm-sepolia-fork', 'vm-merge', 'vm-london', 'vm-berlin',
'hardhat-provider', 'ganache-provider', 'foundry-provider', 'basic-http-provider', 'injected', 'injected-trustwallet', 'injected-optimism-provider', 'injected-arbitrum-one-provider', 'vm-custom-fork', 'vm-goerli-fork', 'vm-mainnet-fork', 'vm-sepolia-fork', 'vm-merge', 'vm-london', 'vm-berlin',
'compileAndRun', 'search', 'recorder', 'fileDecorator', 'codeParser', 'codeFormatter', 'solidityumlgen', 'contractflattener']
// dependentModules shouldn't be manually activated (e.g hardhat is activated by remixd)

@ -129,6 +129,12 @@ export const setupEvents = (plugin: RunTab, dispatch: React.Dispatch<any>) => {
dispatch(fetchAccountsListSuccess(accountsMap))
})
plugin.on('injected-trustwallet', 'accountsChanged', (accounts: Array<string>) => {
const accountsMap = {}
accounts.map(account => { accountsMap[account] = shortenAddress(account, '0')})
dispatch(fetchAccountsListSuccess(accountsMap))
})
setInterval(() => {
fillAccountsList(plugin, dispatch)
updateInstanceBalance(plugin, dispatch)

Loading…
Cancel
Save