diff --git a/apps/remix-ide-e2e/src/tests/terminal.test.ts b/apps/remix-ide-e2e/src/tests/terminal.test.ts index f944b453f9..baf0639cc5 100644 --- a/apps/remix-ide-e2e/src/tests/terminal.test.ts +++ b/apps/remix-ide-e2e/src/tests/terminal.test.ts @@ -217,13 +217,42 @@ module.exports = { .addFile('scripts/log_tx_block.js', { content: scriptBlockAndTransaction } ) .pause(1000) .executeScriptInTerminal('remix.execute(\'scripts/log_tx_block.js\')') - .pause(10000) // check if the input of the transaction is being logged (web3 call) - .journalChildIncludes('0x775526410000000000000000000000000000000000000000000000000000000000000060464c0335b2f1609abd9de25141c0a3b49db516fc7375970dc737c32b986e88e3000000000000000000000000000000000000000000000000000000000000039e000000000000000000000000000000000000000000000000000000000000000602926b30b10e7a514d92bc71e085f5bff2687fac2856ae43ef7621bf1756fa370516d310bec5727543089be9a4d5f68471174ee528e95a2520b0ca36c2b6c6eb0000000000000000000000000000000000000000000000000000000000046f49036f5e4ea4dd042801c8841e3db8e654124305da0f11824fc1db60c405dbb39f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000') + .waitForElementContainsText('*[data-id="terminalJournal"]', '0x775526410000000000000000000000000000000000000000000000000000000000000060464c0335b2f1609abd9de25141c0a3b49db516fc7375970dc737c32b986e88e3000000000000000000000000000000000000000000000000000000000000039e000000000000000000000000000000000000000000000000000000000000000602926b30b10e7a514d92bc71e085f5bff2687fac2856ae43ef7621bf1756fa370516d310bec5727543089be9a4d5f68471174ee528e95a2520b0ca36c2b6c6eb0000000000000000000000000000000000000000000000000000000000046f49036f5e4ea4dd042801c8841e3db8e654124305da0f11824fc1db60c405dbb39f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', 120000) // check if the logsBloom is being logged (web3 call) - .journalChildIncludes('0x00000000000000000000000000100000000000000000020000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000040000000060000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000100000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000001') + .waitForElementContainsText('*[data-id="terminalJournal"]', '0x00000000000000000000000000100000000000000000020000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000040000000060000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000100000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000001', 120000) // check if the logsBloom is being logged (ethers.js call) - .journalChildIncludes('"hex":"0x025cd8"') + .waitForElementContainsText('*[data-id="terminalJournal"]', '"hex":"0x025cd8"', 120000) + }, + + 'Should listen on all transactions #group8': function (browser: NightwatchBrowser) { + browser + .clickLaunchIcon('udapp') // connect to mainnet + .switchEnvironment('External Http Provider') + .waitForElementPresent('[data-id="basic-http-provider-modal-footer-ok-react"]') + .execute(() => { + (document.querySelector('*[data-id="basic-http-providerModalDialogContainer-react"] input[data-id="modalDialogCustomPromp"]') as any).focus() + }, [], () => {}) + .setValue('[data-id="modalDialogCustomPromp"]', 'https://rpc.archivenode.io/e50zmkroshle2e2e50zm0044i7ao04ym') + .modalFooterOKClick('basic-http-provider') + .click('[data-id="terminalClearConsole"]') // clear the console + .click('[data-id="listenNetworkCheckInput"]') // start to listen + .waitForElementContainsText('*[data-id="terminalJournal"]', 'from:', 200000) + .waitForElementContainsText('*[data-id="terminalJournal"]', 'to:', 200000) + .click('[data-id="terminalClearConsole"]') // clear the console + .waitForElementContainsText('*[data-id="terminalJournal"]', 'from:', 200000) + .waitForElementContainsText('*[data-id="terminalJournal"]', 'to:', 200000) + .click('[data-id="listenNetworkCheckInput"]') // stop to listen + .pause(30000) + .click('[data-id="terminalClearConsole"]') // clear the console + .pause(5000) + .click('[data-id="terminalClearConsole"]') // clear the console + .pause(20000) + .execute(function () { + return (document.querySelector('[data-id="terminalJournal"]') as any).innerText + }, [], function (result) { + browser.assert.equal(result.value, '', 'terminal log should be empty') + }) } } diff --git a/libs/remix-lib/src/execution/txListener.ts b/libs/remix-lib/src/execution/txListener.ts index 0d5b26eb84..808d9fe4e0 100644 --- a/libs/remix-lib/src/execution/txListener.ts +++ b/libs/remix-lib/src/execution/txListener.ts @@ -1,5 +1,4 @@ 'use strict' -import { each } from 'async' import { ethers } from 'ethers' import { toBuffer, addHexPrefix } from 'ethereumjs-util' import { EventManager } from '../eventManager' @@ -34,8 +33,7 @@ export class TxListener { _listenOnNetwork:boolean _loopId blocks - lastBlock - + constructor (opt, executionContext) { this.event = new EventManager() // has a default for now for backwards compatability @@ -107,8 +105,7 @@ export class TxListener { addExecutionCosts(txResult, tx, execResult) tx.envMode = this.executionContext.getProvider() tx.status = txResult.receipt.status // 0x0 or 0x1 - this._resolve([tx], () => { - }) + this._resolve([tx]) }) }) } @@ -123,9 +120,7 @@ export class TxListener { if (this._loopId) { clearInterval(this._loopId) } - if (this._listenOnNetwork) { - this._startListenOnNetwork() - } + this._listenOnNetwork ? this.startListening() : this.stopListening() } /** @@ -133,7 +128,6 @@ export class TxListener { */ init () { this.blocks = [] - this.lastBlock = -1 } /** @@ -164,34 +158,54 @@ export class TxListener { this._isListening = false } - _startListenOnNetwork () { - this._loopId = setInterval(() => { + async _startListenOnNetwork () { + let lastSeenBlock = this.executionContext.lastBlock?.number - 1 + let processingBlock = false + + const processBlocks = async () => { + if (!this._isListening) return + if (processingBlock) return + processingBlock = true const currentLoopId = this._loopId - this.executionContext.web3().eth.getBlockNumber((error, blockNumber) => { - if (this._loopId === null) return - if (error) return console.log(error) - if (currentLoopId === this._loopId && blockNumber > this.lastBlock) { - let current = this.lastBlock + 1 - this.lastBlock = blockNumber - while (blockNumber >= current) { - try { - this._manageBlock(current) - } catch (e) { - console.log(e) - } - current++ + if (this._loopId === null) { + processingBlock = false + return + } + if (!lastSeenBlock) { + lastSeenBlock = this.executionContext.lastBlock?.number // trying to resynchronize + console.log('listen on blocks, resynchronising') + processingBlock = false + return + } + const current = this.executionContext.lastBlock?.number + if (!current) { + console.log(new Error('no last block found')) + processingBlock = false + return + } + if (currentLoopId === this._loopId && lastSeenBlock < current) { + while (lastSeenBlock <= current) { + try { + if (!this._isListening) break + await this._manageBlock(lastSeenBlock) + } catch (e) { + console.log(e) } + lastSeenBlock++ } - }) - }, 2000) + lastSeenBlock = current + } + processingBlock = false + } + this._loopId = setInterval(processBlocks, 20000) + processBlocks() } - _manageBlock (blockNumber) { - this.executionContext.web3().eth.getBlock(blockNumber, true, (error, result) => { - if (!error) { - this._newBlock(Object.assign({ type: 'web3' }, result)) - } - }) + async _manageBlock (blockNumber) { + try { + const result = await this.executionContext.web3().eth.getBlock(blockNumber, true) + return await this._newBlock(Object.assign({ type: 'web3' }, result)) + } catch (e) {} } /** @@ -215,31 +229,37 @@ export class TxListener { return this._resolvedTransactions[txHash] } - _newBlock (block) { + async _newBlock (block) { this.blocks.push(block) - this._resolve(block.transactions, () => { - this.event.trigger('newBlock', [block]) - }) + await this._resolve(block.transactions) + this.event.trigger('newBlock', [block]) } - _resolve (transactions, callback) { - each(transactions, (tx, cb) => { + _resolveAsync (tx) { + return new Promise((resolve, reject) => { this._api.resolveReceipt(tx, (error, receipt) => { - if (error) return cb(error) + if (error) return reject(error) this._resolveTx(tx, receipt, (error, resolvedData) => { - if (error) cb(error) + if (error) return reject(error) if (resolvedData) { this.event.trigger('txResolved', [tx, receipt, resolvedData]) } this.event.trigger('newTransaction', [tx, receipt]) - cb() + resolve({}) }) }) - }, () => { - callback() }) } + async _resolve (transactions) { + for (const tx of transactions) { + try { + if (!this._isListening) break + await this._resolveAsync(tx) + } catch (e) {} + } + } + _resolveTx (tx, receipt, cb) { const contracts = this._api.contracts() if (!contracts) return cb() diff --git a/libs/remix-ui/terminal/src/lib/actions/terminalAction.ts b/libs/remix-ui/terminal/src/lib/actions/terminalAction.ts index 5871a4d2cd..87951d8a98 100644 --- a/libs/remix-ui/terminal/src/lib/actions/terminalAction.ts +++ b/libs/remix-ui/terminal/src/lib/actions/terminalAction.ts @@ -115,7 +115,7 @@ export const initListeningOnNetwork = (plugins, dispatch: React.Dispatch) = plugins.txListener.event.register(NEW_BLOCK, (block) => { if (!block.transactions || (block.transactions && !block.transactions.length)) { - dispatch({ type: EMPTY_BLOCK, payload: { message: 0, provider } }) + dispatch({ type: EMPTY_BLOCK, payload: { message: block.number, provider } }) } }) plugins.txListener.event.register(KNOWN_TRANSACTION, () => { diff --git a/libs/remix-ui/terminal/src/lib/remix-ui-terminal.tsx b/libs/remix-ui/terminal/src/lib/remix-ui-terminal.tsx index 4962101798..11a3cbd57d 100644 --- a/libs/remix-ui/terminal/src/lib/remix-ui-terminal.tsx +++ b/libs/remix-ui/terminal/src/lib/remix-ui-terminal.tsx @@ -461,6 +461,7 @@ export const RemixUiTerminal = (props: RemixUiTerminalProps) => { className="pt-1 form-check-label custom-control-label text-nowrap" title="If checked Remix will listen on all transactions mined in the current environment and not only transactions created by you" htmlFor="listenNetworkCheck" + data-id="listenNetworkCheckInput" > listen on all transactions