mirror of https://github.com/embarklabs/embark.git
Merge pull request #1220 from embark-framework/feat/enable-regular-txs
feat(@embark/core): Disable regular txs until needed
This commit is contained in:
commit
05803fcf42
|
@ -426,6 +426,13 @@ export const removeEditorTabs = {
|
|||
failure: () => action(REMOVE_EDITOR_TABS[FAILURE])
|
||||
};
|
||||
|
||||
export const INIT_REGULAR_TXS = createRequestTypes('INIT_REGULAR_TXS');
|
||||
export const initRegularTxs = {
|
||||
request: () => action(INIT_REGULAR_TXS[REQUEST], {mode: 'on'}),
|
||||
success: () => action(INIT_REGULAR_TXS[SUCCESS]),
|
||||
failure: () => action(INIT_REGULAR_TXS[FAILURE])
|
||||
};
|
||||
|
||||
// Web Socket
|
||||
export const WATCH_NEW_PROCESS_LOGS = 'WATCH_NEW_PROCESS_LOGS';
|
||||
export const STOP_NEW_PROCESS_LOGS = 'STOP_NEW_PROCESS_LOGS';
|
||||
|
|
|
@ -6,7 +6,7 @@ import routes from '../routes';
|
|||
import Login from '../components/Login';
|
||||
import Layout from "../components/Layout";
|
||||
import {DEFAULT_HOST} from '../constants';
|
||||
import {getQueryToken, stripQueryToken} from '../utils/utils';
|
||||
import {getQueryToken, stripQueryToken, getQueryParam, stripQueryParam} from '../utils/utils';
|
||||
import {Helmet} from "react-helmet";
|
||||
|
||||
import {
|
||||
|
@ -16,6 +16,7 @@ import {
|
|||
plugins as pluginsAction,
|
||||
listenToServices as listenToServicesAction,
|
||||
listenToContracts as listenToContractsAction,
|
||||
initRegularTxs as initRegularTxsAction,
|
||||
changeTheme, fetchTheme
|
||||
} from '../actions';
|
||||
|
||||
|
@ -25,6 +26,8 @@ import {
|
|||
getCredentials, getAuthenticationError, getProcesses, getTheme
|
||||
} from '../reducers/selectors';
|
||||
|
||||
const ENABLE_REGULAR_TXS = 'enableRegularTxs';
|
||||
|
||||
class AppContainer extends Component {
|
||||
componentDidMount() {
|
||||
this.props.fetchCredentials();
|
||||
|
@ -50,26 +53,28 @@ class AppContainer extends Component {
|
|||
|
||||
const queryToken = getQueryToken(this.props.location);
|
||||
if (queryToken && !(queryToken === this.props.credentials.token &&
|
||||
this.props.credentials.host === DEFAULT_HOST)) {
|
||||
this.props.credentials.host === DEFAULT_HOST)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!this.props.credentials.authenticated &&
|
||||
this.props.credentials.host &&
|
||||
this.props.credentials.token) {
|
||||
this.props.credentials.host &&
|
||||
this.props.credentials.token) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
componentDidUpdate(){
|
||||
componentDidUpdate() {
|
||||
if (this.requireAuthentication()) {
|
||||
this.doAuthenticate();
|
||||
}
|
||||
|
||||
if (getQueryToken(this.props.location) &&
|
||||
(!this.props.credentials.authenticating ||
|
||||
const enableRegularTxs = !!getQueryParam(this.props.location, ENABLE_REGULAR_TXS);
|
||||
|
||||
if (getQueryToken(this.props.location) &&
|
||||
(!this.props.credentials.authenticating ||
|
||||
this.props.credentials.authenticated)) {
|
||||
this.props.history.replace(stripQueryToken(this.props.location));
|
||||
}
|
||||
|
@ -80,6 +85,10 @@ class AppContainer extends Component {
|
|||
this.props.listenToServices();
|
||||
this.props.fetchPlugins();
|
||||
this.props.listenToContracts();
|
||||
if (enableRegularTxs) {
|
||||
this.props.initRegularTxs();
|
||||
this.props.history.replace(stripQueryParam(this.props.location, ENABLE_REGULAR_TXS));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -99,18 +108,18 @@ class AppContainer extends Component {
|
|||
renderBody() {
|
||||
if (this.shouldRenderLogin()) {
|
||||
return (
|
||||
<Login credentials={this.props.credentials}
|
||||
authenticate={this.props.authenticate}
|
||||
error={this.props.authenticationError} />
|
||||
<Login credentials={this.props.credentials}
|
||||
authenticate={this.props.authenticate}
|
||||
error={this.props.authenticationError} />
|
||||
);
|
||||
} else if (this.props.credentials.authenticating) {
|
||||
return <React.Fragment/>;
|
||||
return <React.Fragment />;
|
||||
}
|
||||
return (
|
||||
<Layout location={this.props.location}
|
||||
logout={this.props.logout}
|
||||
toggleTheme={() => this.toggleTheme()}
|
||||
currentTheme={this.props.theme}>
|
||||
logout={this.props.logout}
|
||||
toggleTheme={() => this.toggleTheme()}
|
||||
currentTheme={this.props.theme}>
|
||||
<React.Fragment>{routes}</React.Fragment>
|
||||
</Layout>
|
||||
);
|
||||
|
@ -148,7 +157,8 @@ AppContainer.propTypes = {
|
|||
fetchTheme: PropTypes.func,
|
||||
history: PropTypes.object,
|
||||
listenToServices: PropTypes.func,
|
||||
listenToContracts: PropTypes.func
|
||||
listenToContracts: PropTypes.func,
|
||||
initRegularTxs: PropTypes.func
|
||||
};
|
||||
|
||||
function mapStateToProps(state) {
|
||||
|
@ -173,6 +183,7 @@ export default withRouter(connect(
|
|||
fetchPlugins: pluginsAction.request,
|
||||
changeTheme: changeTheme.request,
|
||||
fetchTheme: fetchTheme.request,
|
||||
listenToContracts: listenToContractsAction
|
||||
listenToContracts: listenToContractsAction,
|
||||
initRegularTxs: initRegularTxsAction.request
|
||||
},
|
||||
)(AppContainer));
|
||||
|
|
|
@ -79,6 +79,7 @@ export const debugStepIntoForward = doRequest.bind(null, actions.debugStepIntoFo
|
|||
export const debugStepIntoBackward = doRequest.bind(null, actions.debugStepIntoBackward, api.debugStepIntoBackward);
|
||||
export const toggleBreakpoint = doRequest.bind(null, actions.toggleBreakpoint, api.toggleBreakpoint);
|
||||
export const authenticate = doRequest.bind(null, actions.authenticate, api.authenticate);
|
||||
export const initRegularTxs = doRequest.bind(null, actions.initRegularTxs, api.initRegularTxs);
|
||||
|
||||
export const fetchCredentials = doRequest.bind(null, actions.fetchCredentials, storage.fetchCredentials);
|
||||
export const saveCredentials = doRequest.bind(null, actions.saveCredentials, storage.saveCredentials);
|
||||
|
@ -343,6 +344,10 @@ export function *watchRemoveEditorTabsSuccess() {
|
|||
yield takeEvery(actions.REMOVE_EDITOR_TABS[actions.SUCCESS], fetchEditorTabs);
|
||||
}
|
||||
|
||||
export function *watchInitRegularTxs() {
|
||||
yield takeEvery(actions.INIT_REGULAR_TXS[actions.REQUEST], initRegularTxs);
|
||||
}
|
||||
|
||||
function createChannel(socket) {
|
||||
return eventChannel(emit => {
|
||||
socket.onmessage = ((message) => {
|
||||
|
@ -585,6 +590,7 @@ export default function *root() {
|
|||
fork(watchRemoveEditorTabsSuccess),
|
||||
fork(watchPostFileSuccess),
|
||||
fork(watchPostFolderSuccess),
|
||||
fork(watchListenContracts)
|
||||
fork(watchListenContracts),
|
||||
fork(watchInitRegularTxs)
|
||||
]);
|
||||
}
|
||||
|
|
|
@ -228,6 +228,10 @@ export function toggleBreakpoint(payload) {
|
|||
return post('/debugger/breakpoint', {params: payload, credentials: payload.credentials});
|
||||
}
|
||||
|
||||
export function initRegularTxs(payload) {
|
||||
return get('/regular-txs', {params: payload, credentials: payload.credentials});
|
||||
}
|
||||
|
||||
export function listenToDebugger(credentials) {
|
||||
return websocket(credentials, '/debugger');
|
||||
}
|
||||
|
|
|
@ -23,8 +23,12 @@ export function ansiToHtml(text) {
|
|||
return convert.toHtml(text.replace(/\n/g,'<br>'));
|
||||
}
|
||||
|
||||
export function getQueryParam(location, param) {
|
||||
return qs.parse(location.search, {ignoreQueryPrefix: true})[param];
|
||||
}
|
||||
|
||||
export function getQueryToken(location) {
|
||||
return qs.parse(location.search, {ignoreQueryPrefix: true}).token;
|
||||
return getQueryParam(location, 'token');
|
||||
}
|
||||
|
||||
export function getDebuggerTransactionHash(location) {
|
||||
|
@ -32,9 +36,13 @@ export function getDebuggerTransactionHash(location) {
|
|||
}
|
||||
|
||||
export function stripQueryToken(location) {
|
||||
return stripQueryParam(location, 'token');
|
||||
}
|
||||
|
||||
export function stripQueryParam(location, param) {
|
||||
const _location = Object.assign({}, location);
|
||||
_location.search = _location.search.replace(
|
||||
/(\?|&?)(token=[\w-]*)(&?)/,
|
||||
new RegExp(`(\\?|&?)(${param}=[\\w-]*)(&?)`),
|
||||
(_, p1, p2, p3) => (p2 ? (p3 === '&' ? p1 : '') : '')
|
||||
);
|
||||
return _location;
|
||||
|
|
|
@ -53,7 +53,9 @@
|
|||
"eth_sendTransaction": "eth_sendTransaction",
|
||||
"eth_sendRawTransaction": "eth_sendRawTransaction",
|
||||
"eth_getTransactionReceipt": "eth_getTransactionReceipt"
|
||||
}
|
||||
},
|
||||
"startRegularTxs": "startRegularTxs",
|
||||
"stopRegularTxs": "stopRegularTxs"
|
||||
},
|
||||
"storage": {
|
||||
"init": "init",
|
||||
|
|
|
@ -26,6 +26,9 @@ class BlockchainListener {
|
|||
|
||||
if (this.ipc.isServer()) {
|
||||
this._listenToBlockchainLogs();
|
||||
this._listenToCommands();
|
||||
this._registerConsoleCommands();
|
||||
this._registerApiEndpoint();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -40,6 +43,43 @@ class BlockchainListener {
|
|||
this.processLogsApi.logHandler.handleLog({logLevel, message});
|
||||
});
|
||||
}
|
||||
|
||||
_registerConsoleCommands() {
|
||||
this.embark.registerConsoleCommand({
|
||||
description: 'Toggles regular transactions used to prevent transactions from getting stuck when using Geth and Metamask',
|
||||
matches: ['regularTxs on', 'regularTxs off'],
|
||||
usage: "regularTxs on/off",
|
||||
process: (cmd, callback) => {
|
||||
const eventCmd = `regularTxs:${cmd.trim().endsWith('on') ? 'start' : 'stop'}`;
|
||||
this.events.request(eventCmd, callback);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
_registerApiEndpoint() {
|
||||
this.embark.registerAPICall(
|
||||
'get',
|
||||
'/embark-api/regular-txs',
|
||||
(req, _res) => {
|
||||
this.events.request(`regularTxs:${req.query.mode === 'on' ? 'start' : 'stop'}`);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
_listenToCommands() {
|
||||
|
||||
this.events.setCommandHandler('regularTxs:start', (cb) => {
|
||||
this.events.emit('regularTxs:start');
|
||||
this.ipc.broadcast('regularTxs', 'start');
|
||||
return cb(null, 'Enabling regular transactions');
|
||||
});
|
||||
|
||||
this.events.setCommandHandler('regularTxs:stop', (cb) => {
|
||||
this.events.emit('regularTxs:stop');
|
||||
this.ipc.broadcast('regularTxs', 'stop');
|
||||
return cb(null, 'Disabling regular transactions');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = BlockchainListener;
|
||||
|
|
|
@ -65,6 +65,8 @@ var Blockchain = function(userConfig, clientClass) {
|
|||
proxy: this.userConfig.proxy
|
||||
};
|
||||
|
||||
this.devFunds = null;
|
||||
|
||||
if (this.userConfig.accounts) {
|
||||
const nodeAccounts = this.userConfig.accounts.find(account => account.nodeAccounts);
|
||||
if (nodeAccounts) {
|
||||
|
@ -120,7 +122,7 @@ Blockchain.prototype.initStandaloneProcess = function () {
|
|||
if (this.isStandalone) {
|
||||
// on every log logged in logger (say that 3x fast), send the log
|
||||
// to the IPC serve listening (only if we're connected of course)
|
||||
this.events.on('log', (logLevel, message) => {
|
||||
this.logger.events.on('log', (logLevel, message) => {
|
||||
if (this.ipc.connected) {
|
||||
this.ipc.request('blockchain:log', {logLevel, message});
|
||||
}
|
||||
|
@ -133,7 +135,14 @@ Blockchain.prototype.initStandaloneProcess = function () {
|
|||
// `embark run` without restarting `embark blockchain`)
|
||||
setInterval(() => {
|
||||
if (!this.ipc.connected) {
|
||||
this.ipc.connect(() => {});
|
||||
this.ipc.connect(() => {
|
||||
if (this.ipc.connected) {
|
||||
this.ipc.listenTo('regularTxs', (mode) => {
|
||||
if(mode === 'start') this.startRegularTxs(() => {});
|
||||
else if (mode === 'stop') this.stopRegularTxs(() => {});
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}, IPC_CONNECT_INTERVAL);
|
||||
}
|
||||
|
@ -244,11 +253,6 @@ Blockchain.prototype.run = function () {
|
|||
data = data.toString();
|
||||
if (!self.readyCalled && self.client.isReady(data)) {
|
||||
self.readyCalled = true;
|
||||
if (self.isDev) {
|
||||
self.fundAccounts((err) => {
|
||||
if (err) this.logger.error('Error funding accounts', err);
|
||||
});
|
||||
}
|
||||
if (self.config.proxy) {
|
||||
await self.setupProxy();
|
||||
}
|
||||
|
@ -280,14 +284,50 @@ Blockchain.prototype.run = function () {
|
|||
};
|
||||
|
||||
Blockchain.prototype.fundAccounts = function(cb) {
|
||||
DevFunds.new({blockchainConfig: this.config}).then(devFunds => {
|
||||
devFunds.fundAccounts(this.client.needKeepAlive(), (err) => {
|
||||
if(this.isDev && this.devFunds){
|
||||
this.devFunds.fundAccounts((err) => {
|
||||
cb(err);
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
Blockchain.prototype.startRegularTxs = function(cb) {
|
||||
if (this.client.needKeepAlive() && this.devFunds){
|
||||
return this.devFunds.startRegularTxs(() => {
|
||||
this.logger.info('Regular transactions have been enabled.');
|
||||
cb();
|
||||
});
|
||||
}
|
||||
cb();
|
||||
};
|
||||
|
||||
Blockchain.prototype.stopRegularTxs = function(cb) {
|
||||
if (this.client.needKeepAlive() && this.devFunds){
|
||||
return this.devFunds.stopRegularTxs(() => {
|
||||
this.logger.info('Regular transactions have been disabled.');
|
||||
cb();
|
||||
});
|
||||
}
|
||||
cb();
|
||||
};
|
||||
|
||||
Blockchain.prototype.readyCallback = function () {
|
||||
if (this.isDev) {
|
||||
if(!this.devFunds) {
|
||||
DevFunds.new({blockchainConfig: this.config}).then(devFunds => {
|
||||
this.devFunds = devFunds;
|
||||
this.fundAccounts((err) => {
|
||||
if (err) this.logger.error('Error funding accounts', err);
|
||||
});
|
||||
});
|
||||
}
|
||||
else {
|
||||
this.fundAccounts((err) => {
|
||||
if (err) this.logger.error('Error funding accounts', err);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (this.onReadyCallback) {
|
||||
this.onReadyCallback();
|
||||
}
|
||||
|
@ -450,7 +490,7 @@ Blockchain.prototype.initChainAndGetAddress = function (callback) {
|
|||
});
|
||||
};
|
||||
|
||||
var BlockchainClient = function(userConfig, clientName, env, certOptions, onReadyCallback, onExitCallback, logger, _events, _isStandalone) {
|
||||
var BlockchainClient = function(userConfig, clientName, env, certOptions, onReadyCallback, onExitCallback, logger, _events, isStandalone) {
|
||||
if ((userConfig === {} || JSON.stringify(userConfig) === '{"enabled":true}') && env !== 'development') {
|
||||
logger.info("===> " + __("warning: running default config on a non-development environment"));
|
||||
}
|
||||
|
@ -478,6 +518,7 @@ var BlockchainClient = function(userConfig, clientName, env, certOptions, onRead
|
|||
userConfig.onExitCallback = onExitCallback;
|
||||
userConfig.logger = logger;
|
||||
userConfig.certOptions = certOptions;
|
||||
userConfig.isStandalone = isStandalone;
|
||||
return new Blockchain(userConfig, clientClass);
|
||||
};
|
||||
|
||||
|
|
|
@ -52,4 +52,10 @@ process.on('message', (msg) => {
|
|||
blockchainProcess = new BlockchainProcess(msg.options);
|
||||
return blockchainProcess.send({result: constants.blockchain.initiated});
|
||||
}
|
||||
else if(msg.action === constants.blockchain.startRegularTxs){
|
||||
blockchainProcess.blockchain.startRegularTxs(() => {});
|
||||
}
|
||||
else if(msg.action === constants.blockchain.stopRegularTxs){
|
||||
blockchainProcess.blockchain.stopRegularTxs(() => {});
|
||||
}
|
||||
});
|
||||
|
|
|
@ -38,7 +38,8 @@ class BlockchainProcessLauncher {
|
|||
env: this.env,
|
||||
isDev: this.isDev,
|
||||
locale: this.locale,
|
||||
certOptions: this.embark.config.webServerConfig.certOptions
|
||||
certOptions: this.embark.config.webServerConfig.certOptions,
|
||||
events: this.events
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -62,6 +63,14 @@ class BlockchainProcessLauncher {
|
|||
this.events.on('logs:ethereum:disable', () => {
|
||||
this.blockchainProcess.silent = true;
|
||||
});
|
||||
|
||||
this.events.on('regularTxs:start', () => {
|
||||
this.blockchainProcess.send({action: constants.blockchain.startRegularTxs});
|
||||
});
|
||||
|
||||
this.events.on('regularTxs:stop', () => {
|
||||
this.blockchainProcess.send({action: constants.blockchain.stopRegularTxs});
|
||||
});
|
||||
|
||||
this.events.on('exit', () => {
|
||||
this.blockchainProcess.send('exit');
|
||||
|
|
|
@ -60,20 +60,28 @@ class DevFunds {
|
|||
this.web3.eth.sendTransaction({value: "1000000000000000", to: "0xA2817254cb8E7b6269D1689c3E0eBadbB78889d1", from: this.web3.eth.defaultAccount});
|
||||
}
|
||||
|
||||
_regularTxs(cb) {
|
||||
startRegularTxs(cb) {
|
||||
const self = this;
|
||||
self.web3.eth.net.getId().then((networkId) => {
|
||||
self.networkId = networkId;
|
||||
if (self.networkId !== 1337) {
|
||||
return;
|
||||
}
|
||||
setInterval(function() { self._sendTx(); }, 1500);
|
||||
this.regularTxsInt = setInterval(function() { self._sendTx(); }, 1500);
|
||||
if (cb) {
|
||||
cb();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
stopRegularTxs(cb) {
|
||||
if(this.regularTxsInt) {
|
||||
clearInterval(this.regularTxsInt);
|
||||
return cb();
|
||||
}
|
||||
cb('Regular txs not enabled.');
|
||||
}
|
||||
|
||||
_fundAccounts(balance, cb) {
|
||||
async.each(this.accounts, (account, next) => {
|
||||
this.web3.eth.getBalance(account).then(currBalance => {
|
||||
|
@ -113,13 +121,12 @@ class DevFunds {
|
|||
}, cb);
|
||||
}
|
||||
|
||||
fundAccounts(pingForever = false, cb) {
|
||||
fundAccounts(cb) {
|
||||
if (!this.web3) {
|
||||
return cb();
|
||||
}
|
||||
async.waterfall([
|
||||
(next) => {
|
||||
if (pingForever) this._regularTxs();
|
||||
this._fundAccounts(this.balance, next);
|
||||
}
|
||||
], cb);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
EmbarkJS.Blockchain.autoEnable = <%= autoEnable %>;
|
||||
EmbarkJS.Blockchain.connect(<%- connectionList %>, {warnAboutMetamask: <%= warnAboutMetamask %>}, function(err) {
|
||||
EmbarkJS.Blockchain.connect(<%- connectionList %>, {warnAboutMetamask: <%= warnAboutMetamask %>, blockchainClient: "<%= blockchainClient %>"}, function(err) {
|
||||
<%- done %>
|
||||
});
|
||||
|
|
|
@ -26,6 +26,7 @@ class CodeGenerator {
|
|||
this.storageConfig = embark.config.storageConfig || {};
|
||||
this.communicationConfig = embark.config.communicationConfig || {};
|
||||
this.namesystemConfig = embark.config.namesystemConfig || {};
|
||||
this.webServerConfig = embark.config.webServerConfig || {};
|
||||
this.env = options.env || 'development';
|
||||
this.plugins = options.plugins;
|
||||
this.events = embark.events;
|
||||
|
@ -124,7 +125,8 @@ class CodeGenerator {
|
|||
autoEnable: this.contractsConfig.dappAutoEnable,
|
||||
connectionList: connectionList,
|
||||
done: 'done(err);',
|
||||
warnAboutMetamask: isDev
|
||||
warnAboutMetamask: isDev,
|
||||
blockchainClient: this.blockchainConfig.ethereumClientName
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -110,7 +110,7 @@ describe('embark.DevFunds', function() {
|
|||
// provider.injectResult('0x11f4d0A3c12e86B4b5F39B213F7E19D048276DAe'); // send tx response
|
||||
});
|
||||
|
||||
devFunds.fundAccounts(devFunds.balance, (errFundAccounts) => {
|
||||
devFunds.fundAccounts((errFundAccounts) => {
|
||||
assert.equal(errFundAccounts, null);
|
||||
|
||||
// inject response for web3.eth.getAccounts
|
||||
|
|
Loading…
Reference in New Issue