src/modules/universe/actions/load-universe-info.js
import { augur } from "services/augurjs";
import { UNIVERSE_ID } from "modules/app/constants/network";
import logError from "utils/log-error";
import async from "async";
import { createBigNumber } from "utils/create-big-number";
import { updateUniverse } from "modules/universe/actions/update-universe";
import { loadMarketsInfoIfNotLoaded } from "modules/markets/actions/load-markets-info";
import { selectReportableOutcomes } from "modules/reports/selectors/reportable-outcomes";
import calculatePayoutNumeratorsValue from "utils/calculate-payout-numerators-value";
import { SCALAR } from "modules/markets/constants/market-types";
import { NULL_ADDRESS } from "utils/constants";
const REQUIRED_GENESIS_SUPPLY = createBigNumber(
"1100000000000000000000000",
10
);
export function loadUniverseInfo(callback = logError) {
return (dispatch, getState) => {
const { universe, loginAccount, marketsData } = getState();
const universeId = universe.id || UNIVERSE_ID;
const universeData = {
market: null,
id: universeId,
reportableOutcomes: null,
winningChildUniverseId: null,
openInterest: universe.openInterest || "0"
};
if (universe.isForking && marketsData[universe.forkingMarket]) {
const forkingMarket = marketsData[universe.forkingMarket];
universeData.market = forkingMarket;
universeData.reportableOutcomes = selectReportableOutcomes(
forkingMarket.marketType,
forkingMarket.outcomes
);
universeData.winningChildUniverseId = universe.winningChildUniverse;
}
augur.api.Universe.getParentUniverse(
{ tx: { to: universeId } },
(err, parentUniverseId) => {
if (err) return callback(err);
if (parentUniverseId === NULL_ADDRESS) {
return getUniversesInfoWithParentContext(
loginAccount.address,
universeData,
{ id: parentUniverseId },
{ id: parentUniverseId },
callback
);
}
getUniverseInfo(parentUniverseId, (err, parentUniverseData) => {
if (err) return callback(err);
augur.api.Universe.getParentUniverse(
{ tx: { to: parentUniverseData.id } },
(err, grandParentUniverseId) => {
if (err) return callback(err);
if (grandParentUniverseId === NULL_ADDRESS) {
return getUniversesInfoWithParentContext(
loginAccount.address,
universeData,
parentUniverseData,
{ id: grandParentUniverseId },
callback
);
}
getUniverseInfo(
grandParentUniverseId,
(err, grandParentUniverseData) => {
if (err) return callback(err);
return getUniversesInfoWithParentContext(
loginAccount.address,
universeData,
parentUniverseData,
grandParentUniverseData,
callback
);
}
);
}
);
});
}
);
};
}
function getUniverseInfo(universeId, callback) {
const universeData = {
id: universeId,
reportableOutcomes: null,
winningChildUniverseId: null,
market: null,
openInterest: "0"
};
augur.api.Universe.getForkingMarket(
{ tx: { to: universeId } },
(err, forkingMarket) => {
if (err) return callback(err);
augur.markets.getMarketsInfo(
{ marketIds: [forkingMarket] },
(err, marketsDataArray) => {
if (err) return callback(err);
universeData.market = marketsDataArray[0];
universeData.reportableOutcomes = selectReportableOutcomes(
universeData.market.marketType,
universeData.market.outcomes
);
augur.api.Market.isFinalized(
{ tx: { to: forkingMarket } },
(err, isForkingMarketFinalized) => {
if (err) return callback(err);
if (!isForkingMarketFinalized) {
return callback(null, universeData);
}
augur.api.Universe.getWinningChildUniverse(
{ tx: { to: universeId } },
(err, winningChildUniverse) => {
if (err) return callback(err);
universeData.winningChildUniverseId = winningChildUniverse;
return callback(null, universeData);
}
);
}
);
}
);
}
);
}
function getUniversesInfoWithParentContext(
account,
currentUniverseData,
parentUniverseData,
grandParentUniverseData,
callback
) {
augur.augurNode.submitRequest(
"getUniversesInfo",
{
universe: currentUniverseData.id,
account
},
(err, result) => {
if (err) return callback(err);
const initialMapping = {
parent: null,
children: [],
currentLevel: []
};
async.forEachOf(
result,
(obj, key, callback) => {
augur.api.Universe.getOpenInterestInAttoEth(
{ tx: { to: obj.universe } },
(err, openInterest) => {
// give default value of 0, there might have been error
obj.openInterest = openInterest || 0;
callback(err, obj);
}
);
},
err => {
callback(
err,
result.reduce((acc, universeData) => {
const supply = createBigNumber(universeData.supply || "0", 10);
if (
universeData.parentUniverse ===
"0x0000000000000000000000000000000000000000" &&
supply.lt(REQUIRED_GENESIS_SUPPLY) &&
universeData.numMarkets === 0
) {
return acc;
} else if (
universeData.parentUniverse === currentUniverseData.id
) {
universeData.description = getUniverseName(
currentUniverseData,
universeData
);
universeData.isWinningUniverse =
currentUniverseData.winningChildUniverseId ===
universeData.universe;
acc.children.push(universeData);
} else if (
universeData.parentUniverse === parentUniverseData.id
) {
universeData.description = getUniverseName(
parentUniverseData,
universeData
);
universeData.isWinningUniverse =
parentUniverseData.winningChildUniverseId ===
universeData.universe;
if (universeData.universe === currentUniverseData.id) {
acc.currentLevel = [universeData].concat(acc.currentLevel);
} else {
acc.currentLevel.push(universeData);
}
} else {
universeData.description = getUniverseName(
grandParentUniverseData,
universeData
);
universeData.isWinningUniverse =
grandParentUniverseData.winningChildUniverseId ===
universeData.universe;
acc.parent = universeData;
}
return acc;
}, initialMapping)
);
}
);
}
);
}
function getUniverseName(parentUniverseData, universeData) {
if (!parentUniverseData.market) return "GENESIS";
if (universeData.isInvalid) return "Invalid";
const outcomeId = calculatePayoutNumeratorsValue(
parentUniverseData.market,
universeData.payout,
universeData.isInvalid
).toString();
if (parentUniverseData.market.marketType === SCALAR) {
return outcomeId;
}
const outcome = parentUniverseData.reportableOutcomes[outcomeId];
const outComeLabel = outcome && (outcome.description || outcome.name);
return outComeLabel || "Unidentified";
}
export function getForkingInfo(universe, callback) {
return (dispatch, getState) => {
const universePayload = { tx: { to: universe.id } };
// Getting current fork data
augur.api.Universe.getForkingMarket(
universePayload,
(err, forkingMarket) => {
if (err) return callback(err);
const isForking =
forkingMarket !== "0x0000000000000000000000000000000000000000";
if (isForking) {
dispatch(loadMarketsInfoIfNotLoaded([forkingMarket]));
async.parallel(
{
forkEndTime: next => {
augur.api.Universe.getForkEndTime(
universePayload,
(err, forkEndTime) => {
if (err) return next(err);
next(null, forkEndTime);
}
);
},
isForkingMarketFinalized: next => {
augur.api.Market.isFinalized(
{ tx: { to: forkingMarket } },
(err, isForkingMarketFinalized) => {
if (err) return next(err);
next(null, isForkingMarketFinalized);
}
);
},
forkReputationGoal: next => {
augur.api.Universe.getForkReputationGoal(
universePayload,
(err, forkReputationGoal) => {
if (err) return next(err);
next(null, forkReputationGoal);
}
);
}
},
(err, universeData) => {
if (err) return callback(err);
if (universeData.isForkingMarketFinalized) {
augur.api.Universe.getWinningChildUniverse(
universePayload,
(err, winningChildUniverse) => {
if (err) return callback(err);
updateUniverseIfForkingDataChanged(dispatch, universe, {
...universeData,
forkingMarket,
winningChildUniverse,
isForking
});
}
);
} else {
updateUniverseIfForkingDataChanged(dispatch, universe, {
...universeData,
forkingMarket,
isForking,
winningChildUniverse: undefined
});
}
}
);
} else {
updateUniverseIfForkingDataChanged(dispatch, universe, {
isForking,
forkingMarket,
forkEndTime: undefined,
isForkingMarketFinalized: undefined,
winningChildUniverse: undefined
});
}
}
);
};
}
function updateUniverseIfForkingDataChanged(
dispatch,
oldUniverseData,
universeData
) {
if (
oldUniverseData.id !== universeData.id ||
oldUniverseData.isForking !== universeData.isForking ||
oldUniverseData.forkingMarket !== universeData.forkingMarket ||
oldUniverseData.forkEndTime !== universeData.forkEndTime ||
oldUniverseData.isForkingMarketFinalized !==
universeData.isForkingMarketFinalized ||
oldUniverseData.winningChildUniverse !== universeData.winningChildUniverse
) {
dispatch(updateUniverse(universeData));
}
}
export function getUniverseProperties(universe, callback) {
return (dispatch, getState) => {
const universePayload = { tx: { to: universe.id } };
async.parallel(
{
forkThreshold: next => {
augur.api.Universe.getDisputeThresholdForFork(
universePayload,
(err, disputeThresholdForFork) => {
if (err) return callback(err);
const forkThreshold = createBigNumber(
disputeThresholdForFork,
10
);
if (forkThreshold !== universe.forkThreshold) {
next(null, forkThreshold);
}
}
);
},
openInterest: next => {
augur.api.Universe.getOpenInterestInAttoEth(
universePayload,
(err, openInterest) => {
if (err) return next(err);
next(null, openInterest);
}
);
}
},
(err, universeData) => {
dispatch(updateUniverse(universeData));
}
);
};
}