From 1cc79983bd8a717d33a2937e030818bfdd93987f Mon Sep 17 00:00:00 2001 From: Iuri Matias Date: Thu, 19 Apr 2018 15:19:39 -0400 Subject: [PATCH] move provider code from remix-tests to remix-simulator --- remix-simulator/README.md | 2 + remix-simulator/package.json | 73 ++++++++++++++++++++++++ remix-simulator/src/provider.js | 76 +++++++++++++++++++++++++ remix-simulator/src/txProcess.js | 98 ++++++++++++++++++++++++++++++++ 4 files changed, 249 insertions(+) create mode 100644 remix-simulator/README.md create mode 100644 remix-simulator/package.json create mode 100644 remix-simulator/src/provider.js create mode 100644 remix-simulator/src/txProcess.js diff --git a/remix-simulator/README.md b/remix-simulator/README.md new file mode 100644 index 0000000000..ea0ecbddb0 --- /dev/null +++ b/remix-simulator/README.md @@ -0,0 +1,2 @@ +# `remix-simulator` + diff --git a/remix-simulator/package.json b/remix-simulator/package.json new file mode 100644 index 0000000000..29c65a855f --- /dev/null +++ b/remix-simulator/package.json @@ -0,0 +1,73 @@ +{ + "name": "remix-simulator", + "version": "0.0.1", + "description": "Ethereum IDE and tools for the web", + "contributors": [ + { + "name": "Iuri Matias", + "email": "iuri@ethereum.org" + }, + { + "name": "Yann Levreau", + "email": "yann@ethdev.com" + } + ], + "main": "./index.js", + "dependencies": { + "remix-lib": "latest", + "standard": "^10.0.3", + "web3": "1.0.0-beta.27" + }, + "scripts": { + "test": "standard" + }, + "standard": { + "ignore": [ + "node_modules/*", + ], + "parser": "babel-eslint" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/ethereum/remix.git" + }, + "author": "remix team", + "license": "MIT", + "bugs": { + "url": "https://github.com/ethereum/remix/issues" + }, + "homepage": "https://github.com/ethereum/remix#readme", + "browserify": { + "transform": [ + [ + "babelify", + { + "plugins": [ + [ + "fast-async", + { + "runtimePatten": null, + "compiler": { + "promises": true, + "es7": true, + "noRuntime": true, + "wrapAwait": true + } + } + ], + "transform-object-assign" + ] + } + ], + [ + "babelify", + { + "presets": [ + "es2017" + ] + } + ] + ] + } +} + diff --git a/remix-simulator/src/provider.js b/remix-simulator/src/provider.js new file mode 100644 index 0000000000..9a0b61e3be --- /dev/null +++ b/remix-simulator/src/provider.js @@ -0,0 +1,76 @@ +var Web3 = require('web3') +var RemixLib = require('remix-lib') +var executionContext = RemixLib.execution.executionContext + +var processTx = require('./txProcess.js') + +function jsonRPCResponse (id, result) { + return {'id': id, 'jsonrpc': '2.0', 'result': result} +} + +var Provider = function () { + this.web3 = new Web3() + // TODO: make it random + this.accounts = [this.web3.eth.accounts.create(['abcd'])] + + this.accounts[this.accounts[0].address.toLowerCase()] = this.accounts[0] + this.accounts[this.accounts[0].address.toLowerCase()].privateKey = Buffer.from(this.accounts[this.accounts[0].address.toLowerCase()].privateKey.slice(2), 'hex') + + // TODO: fix me; this is a temporary and very hackish thing just to get the getCode working for now + this.deployedContracts = {} +} + +Provider.prototype.sendAsync = function (payload, callback) { + const self = this + + if (payload.method === 'eth_accounts') { + return callback(null, jsonRPCResponse(payload.id, this.accounts.map((x) => x.address))) + } + if (payload.method === 'eth_estimateGas') { + callback(null, jsonRPCResponse(payload.id, 3000000)) + } + if (payload.method === 'eth_gasPrice') { + callback(null, jsonRPCResponse(payload.id, 1)) + } + if (payload.method === 'eth_sendTransaction') { + processTx(this.accounts, payload, false, callback) + } + if (payload.method === 'eth_getTransactionReceipt') { + executionContext.web3().eth.getTransactionReceipt(payload.params[0], (error, receipt) => { + if (error) { + return callback(error) + } + self.deployedContracts[receipt.contractAddress] = receipt.data + + var r = { + 'transactionHash': receipt.hash, + 'transactionIndex': '0x00', + 'blockHash': '0x766d18646a06cf74faeabf38597314f84a82c3851859d9da9d94fc8d037269e5', + 'blockNumber': '0x06', + 'gasUsed': '0x06345f', + 'cumulativeGasUsed': '0x06345f', + 'contractAddress': receipt.contractAddress, + 'logs': [], + 'status': 1 + } + + callback(null, jsonRPCResponse(payload.id, r)) + }) + } + if (payload.method === 'eth_getCode') { + let address = payload.params[0] + // let block = payload.params[1] + + callback(null, jsonRPCResponse(payload.id, self.deployedContracts[address])) + } + if (payload.method === 'eth_call') { + processTx(this.accounts, payload, true, callback) + } +} + +Provider.prototype.isConnected = function () { + return true +} + +module.exports = Provider + diff --git a/remix-simulator/src/txProcess.js b/remix-simulator/src/txProcess.js new file mode 100644 index 0000000000..702fb9d713 --- /dev/null +++ b/remix-simulator/src/txProcess.js @@ -0,0 +1,98 @@ +var RemixLib = require('remix-lib') +var TxExecution = RemixLib.execution.txExecution +var TxRunner = RemixLib.execution.txRunner +var executionContext = RemixLib.execution.executionContext + +function jsonRPCResponse (id, result) { + return {'id': id, 'jsonrpc': '2.0', 'result': result} +} + +function runTx (payload, from, to, data, value, gasLimit, txRunner, callbacks, isCall, callback) { + let finalCallback = function (err, result) { + if (err) { + return callback(err) + } + let toReturn + if (isCall) { + toReturn = '0x' + result.result.vm.return.toString('hex') + if (toReturn === '0x') { + toReturn = '0x0' + } + } else { + toReturn = result.transactionHash + } + + callback(null, jsonRPCResponse(payload.id, toReturn)) + } + + TxExecution.callFunction(from, to, data, value, gasLimit, null, txRunner, callbacks, finalCallback, isCall) +} + +function createContract (payload, from, data, value, gasLimit, txRunner, callbacks, callback) { + let finalCallback = function (err, result) { + if (err) { + return callback(err) + } + // let contractAddress = ('0x' + result.result.createdAddress.toString('hex')) + callback(null, jsonRPCResponse(payload.id, result.transactionHash)) + } + + TxExecution.createContract(from, data, value, gasLimit, txRunner, callbacks, finalCallback) +} + +function processTx (accounts, payload, isCall, callback) { + let api = { + logMessage: (msg) => { + }, + logHtmlMessage: (msg) => { + }, + // config: self._api.config, + config: { + getUnpersistedProperty: (key) => { + // if (key === 'settings/always-use-vm') { + // return true + // } + return true + }, + get: () => { + return true + } + }, + detectNetwork: (cb) => { + cb() + }, + personalMode: () => { + // return self._api.config.get('settings/personal-mode') + return false + } + } + + executionContext.init(api.config) + + let txRunner = new TxRunner(accounts, api) + let { from, to, data, value, gas } = payload.params[0] + gas = gas || 3000000 + + let callbacks = { + confirmationCb: (network, tx, gasEstimation, continueTxExecution, cancelCb) => { + continueTxExecution(null) + }, + gasEstimationForceSend: (error, continueTxExecution, cancelCb) => { + if (error) { + continueTxExecution(error) + } + continueTxExecution() + }, + promptCb: (okCb, cancelCb) => { + okCb() + } + } + + if (to) { + runTx(payload, from, to, data, value, gas, txRunner, callbacks, isCall, callback) + } else { + createContract(payload, from, data, value, gas, txRunner, callbacks, callback) + } +} + +module.exports = processTx