src/modules/app/actions/init-augur.js
import * as AugurJS from "services/augurjs";
import { updateEnv } from "modules/app/actions/update-env";
import {
updateConnectionStatus,
updateAugurNodeConnectionStatus,
updateUseWebsocketToConnectAugurNode
} from "modules/app/actions/update-connection";
import { getAugurNodeNetworkId } from "modules/app/actions/get-augur-node-network-id";
import { updateContractAddresses } from "modules/contracts/actions/update-contract-addresses";
import {
updateFunctionsAPI,
updateEventsAPI
} from "modules/contracts/actions/update-contract-api";
import { useUnlockedAccount } from "modules/auth/actions/use-unlocked-account";
import { logout } from "modules/auth/actions/logout";
import { verifyMatchingNetworkIds } from "modules/app/actions/verify-matching-network-ids";
import { setMarketsAtRiskModalAsSeen } from "modules/modal/actions/update-markets-at-risk-seen-modal";
import { checkIfMainnet } from "modules/app/actions/check-if-mainnet";
import { loadUniverse } from "modules/app/actions/load-universe";
import { registerTransactionRelay } from "modules/transactions/actions/register-transaction-relay";
import { updateModal } from "modules/modal/actions/update-modal";
import { closeModal } from "modules/modal/actions/close-modal";
import { isGoogleBot } from "src/utils/is-google-bot";
import logError from "utils/log-error";
import networkConfig from "config/network";
import { version } from "src/version";
import { updateVersions } from "modules/app/actions/update-versions";
import { defaultTo, isEmpty } from "lodash";
import { NETWORK_NAMES } from "modules/app/constants/network";
import {
MODAL_NETWORK_MISMATCH,
MODAL_NETWORK_DISCONNECTED,
MODAL_DISCLAIMER,
MODAL_V2_MARKETS_ALERT,
MODAL_NETWORK_DISABLED
} from "modules/modal/constants/modal-types";
import {
V2_MARKETS_REVIEW_SEEN,
DISCLAIMER_SEEN
} from "modules/modal/constants/local-storage-keys";
import { windowRef } from "utils/window-ref";
import { setSelectedUniverse } from "modules/auth/actions/selected-universe-management";
import { isPastV2Cutoff } from "modules/markets/helpers/is-market-past-v2-cutoff";
import { selectMarkets } from "src/modules/markets/selectors/markets-all";
const { ACCOUNT_TYPES } = AugurJS.augur.rpc.constants;
const ACCOUNTS_POLL_INTERVAL_DURATION = 10000;
const NETWORK_ID_POLL_INTERVAL_DURATION = 10000;
const ONE_DAY_IN_MS = 1000 * 60 * 60 * 24;
function pollForAccount(dispatch, getState, callback) {
const { loginAccount } = getState();
let accountType =
loginAccount && loginAccount.meta && loginAccount.meta.accountType;
loadAccount(dispatch, null, accountType, (err, loadedAccount) => {
if (err) {
console.error(err);
return callback(err);
}
let account = loadedAccount;
setInterval(() => {
const {
authStatus,
loginAccount,
marketsAtRiskModalSeenThisSession
} = getState();
accountType =
loginAccount && loginAccount.meta && loginAccount.meta.accountType;
if (authStatus.isLogged) {
loadAccount(dispatch, account, accountType, (err, loadedAccount) => {
if (err) console.error(err);
account = loadedAccount;
});
}
// Disclaimer Check
const disclaimerSeen =
windowRef &&
windowRef.localStorage &&
windowRef.localStorage.getItem(DISCLAIMER_SEEN);
const showDisclaimer = () => {
if (!disclaimerSeen) {
dispatch(
updateModal({
type: MODAL_DISCLAIMER
})
);
}
};
// V2 Markets At Risk Check
const markets = selectMarkets(getState());
const hasPositionsInCutoffMarkets = markets
.filter(market => isPastV2Cutoff(market.endTime.timestamp))
.filter(market => market && market.myPositionOutcomes);
const v2MarketAlertSeen =
(windowRef &&
windowRef.localStorage &&
JSON.parse(windowRef.localStorage.getItem(V2_MARKETS_REVIEW_SEEN))) ||
{};
if (!disclaimerSeen) {
showDisclaimer();
} else if (
loginAccount.address &&
!marketsAtRiskModalSeenThisSession &&
hasPositionsInCutoffMarkets &&
hasPositionsInCutoffMarkets.length > 0 &&
!v2MarketAlertSeen[loginAccount.address]
) {
dispatch(setMarketsAtRiskModalAsSeen(true));
dispatch(
updateModal({
type: MODAL_V2_MARKETS_ALERT
})
);
}
}, ACCOUNTS_POLL_INTERVAL_DURATION);
setInterval(() => {
dispatch(setMarketsAtRiskModalAsSeen(false));
}, ONE_DAY_IN_MS);
});
}
function loadAccount(dispatch, existing, accountType, callback) {
let loggedInAccount = null;
const usingMetaMask = accountType === ACCOUNT_TYPES.META_MASK;
if (windowRef.localStorage && windowRef.localStorage.getItem) {
loggedInAccount = windowRef.localStorage.getItem("loggedInAccount");
}
AugurJS.augur.rpc.eth.accounts((err, accounts) => {
if (err) return callback(err);
let account = existing;
if (existing !== accounts[0]) {
account = accounts[0];
if (account && process.env.AUTO_LOGIN) {
dispatch(useUnlockedAccount(account));
} else if (
loggedInAccount &&
usingMetaMask &&
loggedInAccount !== account &&
account
) {
// local storage does not match mm account and mm is signed in
dispatch(useUnlockedAccount(account));
loggedInAccount = account;
} else if (loggedInAccount && loggedInAccount === account) {
// local storage matchs mm account
dispatch(useUnlockedAccount(loggedInAccount));
account = loggedInAccount;
} else if (
!loggedInAccount &&
usingMetaMask &&
existing !== account &&
account
) {
// no local storage set and logged in account does not match mm account, they want to switch accounts
dispatch(useUnlockedAccount(account));
} else if (!account && usingMetaMask) {
// no mm account signed in
dispatch(logout());
account = null;
}
}
callback(null, account);
});
}
function pollForNetwork(dispatch, getState) {
setInterval(() => {
const { modal } = getState();
dispatch(
verifyMatchingNetworkIds((err, expectedNetworkId) => {
if (err) return console.error("pollForNetwork failed", err);
if (expectedNetworkId != null && isEmpty(modal)) {
dispatch(
updateModal({
type: MODAL_NETWORK_MISMATCH,
expectedNetwork:
NETWORK_NAMES[expectedNetworkId] || expectedNetworkId
})
);
} else if (
expectedNetworkId == null &&
modal.type === MODAL_NETWORK_MISMATCH
) {
dispatch(closeModal());
}
})
);
if (!process.env.ENABLE_MAINNET) {
dispatch(
checkIfMainnet((err, isMainnet) => {
if (err) return console.error("pollForNetwork failed", err);
if (isMainnet && isEmpty(modal)) {
dispatch(
updateModal({
type: MODAL_NETWORK_DISABLED
})
);
} else if (!isMainnet && modal.type === MODAL_NETWORK_DISABLED) {
dispatch(closeModal());
}
})
);
}
}, NETWORK_ID_POLL_INTERVAL_DURATION);
}
export function connectAugur(
history,
env,
isInitialConnection = false,
callback = logError
) {
return (dispatch, getState) => {
const { modal, loginAccount } = getState();
AugurJS.connect(
env,
(err, ConnectionInfo) => {
if (err || !ConnectionInfo.augurNode || !ConnectionInfo.ethereumNode) {
return callback(err, ConnectionInfo);
}
const ethereumNodeConnectionInfo = ConnectionInfo.ethereumNode;
dispatch(updateConnectionStatus(true));
dispatch(updateContractAddresses(ethereumNodeConnectionInfo.contracts));
dispatch(updateFunctionsAPI(ethereumNodeConnectionInfo.abi.functions));
dispatch(updateEventsAPI(ethereumNodeConnectionInfo.abi.events));
dispatch(updateAugurNodeConnectionStatus(true));
dispatch(getAugurNodeNetworkId());
dispatch(registerTransactionRelay());
AugurJS.augur.augurNode.getSyncData((err, res) => {
if (!err && res) {
dispatch(
updateVersions({
augurjs: res.version,
augurNode: res.augurNodeVersion,
augurui: version
})
);
}
});
let universeId =
env.universe ||
AugurJS.augur.contracts.addresses[AugurJS.augur.rpc.getNetworkID()]
.Universe;
if (
windowRef.localStorage &&
windowRef.localStorage.getItem &&
loginAccount.address
) {
const storedUniverseId = JSON.parse(
windowRef.localStorage.getItem(loginAccount.address)
).selectedUniverse[
getState().connection.augurNodeNetworkId ||
AugurJS.augur.rpc.getNetworkID().toString()
];
universeId = !storedUniverseId ? universeId : storedUniverseId;
}
const doIt = () => {
dispatch(loadUniverse(universeId, history));
if (modal && modal.type === MODAL_NETWORK_DISCONNECTED)
dispatch(closeModal());
if (isInitialConnection) {
pollForAccount(dispatch, getState);
pollForNetwork(dispatch, getState);
}
callback();
};
if (process.env.NODE_ENV === "development") {
AugurJS.augur.api.Augur.isKnownUniverse(
{
_universe: universeId
},
(err, data) => {
if (data === false) {
dispatch(setSelectedUniverse());
location.reload();
}
doIt();
}
);
} else {
doIt();
}
}
);
};
}
export function initAugur(
history,
{ augurNode, ethereumNodeHttp, ethereumNodeWs, useWeb3Transport },
callback = logError
) {
return (dispatch, getState) => {
const env = networkConfig[`${process.env.ETHEREUM_NETWORK}`];
env.useWeb3Transport = useWeb3Transport;
env["augur-node"] = defaultTo(augurNode, env["augur-node"]);
env["ethereum-node"].http = defaultTo(
ethereumNodeHttp,
env["ethereum-node"].http
);
env["ethereum-node"].ws = defaultTo(
ethereumNodeWs,
// If only the http param is provided we need to prevent this "default from taking precedence.
isEmpty(ethereumNodeHttp) ? env["ethereum-node"].ws : ""
);
env["use-websocket-for-augur-node"] = !isGoogleBot();
if (!env["use-websocket-for-augur-node"]) {
env["ethereum-node"].ws = "";
}
const action = updateUseWebsocketToConnectAugurNode(
env["use-websocket-for-augur-node"]
);
dispatch(action);
if (!env["use-websocket-for-augur-node"]) {
env["augur-node"] = env["augur-node"].replace(/^ws/, "http");
}
dispatch(updateEnv(env));
connectAugur(history, env, true, callback)(dispatch, getState);
};
}