diff --git a/apps/remix-ide-e2e/src/tests/solidityUnittests.test.ts b/apps/remix-ide-e2e/src/tests/solidityUnittests.test.ts index fc3253614d7..2c99c0a6d9a 100644 --- a/apps/remix-ide-e2e/src/tests/solidityUnittests.test.ts +++ b/apps/remix-ide-e2e/src/tests/solidityUnittests.test.ts @@ -132,7 +132,7 @@ module.exports = { .click('*[data-id="testTabCheckAllTests"]') .clickElementAtPosition('.singleTestLabel', 1) .scrollAndClick('*[data-id="testTabRunTestsTabRunAction"]') - .waitForElementContainsText('*[data-id="testTabSolidityUnitTestsOutput"]', 'revert Deploy Failed', 120000) + .waitForElementContainsText('*[data-id="testTabSolidityUnitTestsOutput"]', 'contract deployment failed: revert', 120000) }, 'Should fail when parameters are passed to method in test contract #group3': function (browser: NightwatchBrowser) { diff --git a/apps/remix-ide/src/app/providers/abstract-provider.tsx b/apps/remix-ide/src/app/providers/abstract-provider.tsx index a5185b6129f..ea4cc5e281b 100644 --- a/apps/remix-ide/src/app/providers/abstract-provider.tsx +++ b/apps/remix-ide/src/app/providers/abstract-provider.tsx @@ -14,11 +14,15 @@ export type JsonDataResult = { id: number jsonrpc: string // version result?: any - error?: any + error?: { + code: number, + message: string + data?: string + } errorData?: any } -export type RejectRequest = (error: Error) => void +export type RejectRequest = (error: JsonDataResult) => void export type SuccessRequest = (data: JsonDataResult) => void export interface IProvider { @@ -98,7 +102,7 @@ export abstract class AbstractProvider extends Plugin implements IProvider { sendAsync(data: JsonDataRequest): Promise { // eslint-disable-next-line no-async-promise-executor return new Promise(async (resolve, reject) => { - if (!this.provider) return reject(new Error('provider node set')) + if (!this.provider) return reject({jsonrpc: '2.0', id: data.id, error: { message: 'provider node set', code: -32603 } } as JsonDataResult) this.sendAsyncInternal(data, resolve, reject) }) } @@ -128,7 +132,8 @@ export abstract class AbstractProvider extends Plugin implements IProvider { if (error && error.message && error.message.includes('net_version') && error.message.includes('SERVER_ERROR')) { this.switchAway(true) } - reject(error) + error.code = -32603 + reject({jsonrpc: '2.0', error, id: data.id}) } } else { const result = data.method === 'net_listening' ? 'canceled' : [] diff --git a/apps/remix-ide/src/app/providers/injected-provider.tsx b/apps/remix-ide/src/app/providers/injected-provider.tsx index a4273e0f31a..36c7e35774a 100644 --- a/apps/remix-ide/src/app/providers/injected-provider.tsx +++ b/apps/remix-ide/src/app/providers/injected-provider.tsx @@ -80,7 +80,7 @@ export abstract class InjectedProvider extends Plugin implements IProvider { this.call('notification', 'toast', 'No injected provider (e.g Metamask) has been found.') return resolve({ jsonrpc: '2.0', - error: 'no injected provider found', + error: { message: 'no injected provider found', code: -32603 }, id: data.id }) } @@ -89,7 +89,7 @@ export abstract class InjectedProvider extends Plugin implements IProvider { if (web3Provider.request) resultData = await web3Provider.request({method: data.method, params: data.params}) else if (web3Provider.send) resultData = await web3Provider.send(data.method, data.params) else { - resolve({jsonrpc: '2.0', error: 'provider not valid', id: data.id}) + resolve({jsonrpc: '2.0', error: { message: 'provider not valid', code: -32603 }, id: data.id}) return } if (resultData) { @@ -98,7 +98,7 @@ export abstract class InjectedProvider extends Plugin implements IProvider { } resolve({jsonrpc: '2.0', result: resultData, id: data.id}) } else { - resolve({jsonrpc: '2.0', error: 'no return data provided', id: data.id}) + resolve({jsonrpc: '2.0', result: null, id: data.id}) } } catch (error) { if (error.data && error.data.originalError && error.data.originalError.data) { diff --git a/apps/remix-ide/src/app/tabs/web3-provider.js b/apps/remix-ide/src/app/tabs/web3-provider.js index 1d4655667bf..89b75287390 100644 --- a/apps/remix-ide/src/app/tabs/web3-provider.js +++ b/apps/remix-ide/src/app/tabs/web3-provider.js @@ -64,7 +64,7 @@ export class Web3ProviderModule extends Plugin { try { resultFn(null, await provider.sendAsync(payload)) } catch (e) { - resultFn(e.message) + resultFn(e.error ? new Error(e.error) : new Error(e)) } } else { reject(new Error('User denied permission')) diff --git a/apps/remix-ide/src/blockchain/blockchain.tsx b/apps/remix-ide/src/blockchain/blockchain.tsx index fa210bb8fbd..69e90355264 100644 --- a/apps/remix-ide/src/blockchain/blockchain.tsx +++ b/apps/remix-ide/src/blockchain/blockchain.tsx @@ -940,12 +940,20 @@ export class Blockchain extends Plugin { cb(null, txResult, address, returnValue) } catch (error) { - if (this.isInjectedWeb3()) { - const errorMessage = error.innerError ? error.innerError.message : error.message - const errorData = error.innerError ? error.innerError.data : error.data + const buildError = async (errorMessage, errorData) => { const compiledContracts = await this.call('compilerArtefacts', 'getAllContractDatas') - const injectedError = txExecution.checkError({ errorMessage, errorData }, compiledContracts) - cb(injectedError.message) + return txExecution.checkError({ errorMessage, errorData }, compiledContracts) + } + let errorMessage + let errorData + if (error.innerError) { + errorMessage = error.innerError.message + errorData = error.innerError.data + cb((await buildError(errorMessage, errorData)).message) + } else if (error.message || error.data) { + errorMessage = error.message + errorData = error.data + cb((await buildError(errorMessage, errorData)).message) } else cb(error) } diff --git a/apps/walletconnect/src/services/WalletConnectRemixClient.ts b/apps/walletconnect/src/services/WalletConnectRemixClient.ts index 6f8b494d00a..0a4ccc00460 100644 --- a/apps/walletconnect/src/services/WalletConnectRemixClient.ts +++ b/apps/walletconnect/src/services/WalletConnectRemixClient.ts @@ -24,6 +24,7 @@ export class WalletConnectRemixClient extends PluginClient { chains: Chain[] currentChain: number internalEvents: EventManager + currentAcount: string constructor() { super() @@ -59,7 +60,9 @@ export class WalletConnectRemixClient extends PluginClient { ] const {publicClient} = configureChains(this.chains, [ w3mProvider({projectId: PROJECT_ID}) - ]) + ], { + pollingInterval: 5000 + }) this.wagmiConfig = createConfig({ autoConnect: false, @@ -75,13 +78,17 @@ export class WalletConnectRemixClient extends PluginClient { subscribeToEvents() { this.wagmiConfig.subscribe((event) => { if (event.status === 'connected') { - this.emit('accountsChanged', [event.data.account]) + if (event.data.account !== this.currentAcount) { + this.currentAcount = event.data.account + this.emit('accountsChanged', [event.data.account]) + } if (this.currentChain !== event.data.chain.id) { this.currentChain = event.data.chain.id this.emit('chainChanged', event.data.chain.id) } } else if (event.status === 'disconnected') { this.emit('accountsChanged', []) + this.currentAcount = '' this.emit('chainChanged', 0) this.currentChain = 0 } @@ -106,25 +113,44 @@ export class WalletConnectRemixClient extends PluginClient { if (provider.isMetaMask) { return new Promise((resolve) => { - provider.sendAsync(data, (err, response) => { - if (err) { - console.error(err) - return resolve({jsonrpc: '2.0', result: [], id: data.id}) + provider.sendAsync(data, (error, response) => { + if (error) { + if (error.data && error.data.originalError && error.data.originalError.data) { + resolve({ + jsonrpc: '2.0', + error: error.data.originalError, + id: data.id + }) + } else if (error.data && error.data.message) { + resolve({ + jsonrpc: '2.0', + error: error.data && error.data, + id: data.id + }) + } else { + resolve({ + jsonrpc: '2.0', + error, + id: data.id + }) + } } return resolve(response) }) }) } else { - const message = await provider.request(data) - - return {jsonrpc: '2.0', result: message, id: data.id} + try { + const message = await provider.request(data) + return {jsonrpc: '2.0', result: message, id: data.id} + } catch (e) { + return {jsonrpc: '2.0', error: { message: e.message, code: -32603 }, id: data.id} + } } } } else { - console.error( - `Cannot make ${data.method} request. Remix client is not connected to walletconnect client` - ) - return {jsonrpc: '2.0', result: [], id: data.id} + const err = `Cannot make ${data.method} request. Remix client is not connected to walletconnect client` + console.error(err) + return {jsonrpc: '2.0', error: { message: err, code: -32603 }, id: data.id} } } diff --git a/libs/remix-lib/src/execution/txRunnerWeb3.ts b/libs/remix-lib/src/execution/txRunnerWeb3.ts index 0ddd2fdc3dc..cd4a42ae386 100644 --- a/libs/remix-lib/src/execution/txRunnerWeb3.ts +++ b/libs/remix-lib/src/execution/txRunnerWeb3.ts @@ -175,16 +175,22 @@ export class TxRunnerWeb3 { } } -async function tryTillReceiptAvailable (txhash, web3) { +async function tryTillReceiptAvailable (txhash: string, web3: Web3) { try { const receipt = await web3.eth.getTransactionReceipt(txhash) - if (receipt) return receipt + if (receipt) { + if (!receipt.to && !receipt.contractAddress) { + // this is a contract creation and the receipt doesn't contain a contract address. we have to keep polling... + console.log('this is a contract creation and the receipt does nott contain a contract address. we have to keep polling...') + } else + return receipt + } } catch (e) {} await pause() return await tryTillReceiptAvailable(txhash, web3) } -async function tryTillTxAvailable (txhash, web3) { +async function tryTillTxAvailable (txhash: string, web3: Web3) { try { const tx = await web3.eth.getTransaction(txhash) if (tx && tx.blockHash) return tx diff --git a/libs/remix-simulator/src/methods/transactions.ts b/libs/remix-simulator/src/methods/transactions.ts index 25c751ed4d5..bdf26bfbc3e 100644 --- a/libs/remix-simulator/src/methods/transactions.ts +++ b/libs/remix-simulator/src/methods/transactions.ts @@ -159,6 +159,9 @@ export class Transactions { processTx(this.txRunnerInstance, payload, true, (error, value: VMexecutionResult) => { if (error) return cb(error) const result: RunTxResult = value.result + if (result.execResult && result.execResult.exceptionError && result.execResult.exceptionError.errorType === 'EvmError') { + return cb(result.execResult.exceptionError.error) + } if ((result as any).receipt?.status === '0x0' || (result as any).receipt?.status === 0) { try { const msg = `0x${result.execResult.returnValue.toString('hex') || '0'}` diff --git a/libs/remix-ui/terminal/src/lib/components/Context.tsx b/libs/remix-ui/terminal/src/lib/components/Context.tsx index 1f06c16e2e9..12adc818860 100644 --- a/libs/remix-ui/terminal/src/lib/components/Context.tsx +++ b/libs/remix-ui/terminal/src/lib/components/Context.tsx @@ -47,7 +47,7 @@ const Context = ({opts, provider}: {opts; provider: string}) => {
- [block:{block} txIndex:{i}] + [block:{block.toString()} txIndex:{i.toString()}]
from: {from} @@ -76,7 +76,7 @@ const Context = ({opts, provider}: {opts; provider: string}) => {
- [block:{block} txIndex:{i}] + [block:{block.toString()} txIndex:{i.toString()}]
from: {from}