Skip to content

Commit

Permalink
A robust way to handle small REP amounts and times in CL4R scheme (#2415
Browse files Browse the repository at this point in the history
)

* robust way to handle small rep amounts and times in cl4r scheme

* install missing humanize types
  • Loading branch information
roienatan authored Feb 4, 2021
1 parent 6751a32 commit 63b9441
Show file tree
Hide file tree
Showing 7 changed files with 30 additions and 27 deletions.
11 changes: 11 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@
"fortmatic": "^0.8.2",
"geopattern": "^1.2.3",
"history": "4.9.0",
"humanize-duration": "^3.25.1",
"immutability-helper": "2.6.4",
"interweave": "^11.1.0",
"mixpanel-browser": "^2.29.0",
Expand Down Expand Up @@ -155,6 +156,7 @@
"@types/clone-deep": "^4.0.1",
"@types/geopattern": "^1.2.3",
"@types/graphql": "^14.0.4",
"@types/humanize-duration": "^3.18.1",
"@types/jest": "^24.9.1",
"@types/jquery": "^3.3.31",
"@types/mixpanel-browser": "^2.23.1",
Expand Down
5 changes: 3 additions & 2 deletions src/components/Scheme/CL4R/CL4R.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ import { lock, releaseLocking, extendLocking, redeemLocking, approveTokens } fro
import { showNotification } from "@store/notifications/notifications.reducer";
import { connect } from "react-redux";
import Tooltip from "rc-tooltip";
import { calculateTotalRedeemedAmount, getCL4RParams, getLockingIdsForRedeem, ICL4RParams, secondsToDays } from "./CL4RHelper";
import { calculateTotalRedeemedAmount, getCL4RParams, getLockingIdsForRedeem, ICL4RParams } from "./CL4RHelper";
import BN from "bn.js";
import humanizeDuration from "humanize-duration";

interface IDispatchProps {
lock: typeof lock;
Expand Down Expand Up @@ -266,7 +267,7 @@ const CL4R = (props: IProps) => {
<div className={css.lockTitle}>New Lock</div>
<div className={css.lockDurationLabel}>
<span style={{ marginRight: "5px" }}>Lock Duration</span>
<Tooltip trigger={["hover"]} overlay={`Period: ${secondsToDays(schemeParams.batchTime).toFixed(2)} days`}>
<Tooltip trigger={["hover"]} overlay={`Period: ${humanizeDuration(schemeParams.batchTime * 1000)}`}>
<img width="15px" src="/assets/images/Icon/question-help.svg" />
</Tooltip>
</div>
Expand Down
11 changes: 4 additions & 7 deletions src/components/Scheme/CL4R/CL4RHelper.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { getArcByDAOAddress, numberWithCommas, realMathToBN, realMathToNumber, WEI } from "lib/util";
import { formatTokens, getArcByDAOAddress, realMathToBN, realMathToNumber, toWei, WEI } from "lib/util";
import gql from "graphql-tag";
import * as React from "react";
import moment from "moment-timezone";
import { Address } from "@daostack/arc.js";
import BN from "bn.js";
import Decimal from "decimal.js";
import humanizeDuration from "humanize-duration";

export interface ICL4RParams {
id: Address;
Expand Down Expand Up @@ -71,10 +72,6 @@ export const getCL4RParams = async (daoAddress: string, schemeId: string) => {
return schemeInfoParamsObject;
};

export const secondsToDays = (seconds: number): number => {
return seconds / 86400;
};

export const renderCL4RParams = (CL4RParams: ICL4RParams) => {
const activationTime = moment.unix(Number(CL4RParams.startTime)).utc();
const redeemEnableTime = moment.unix(Number(CL4RParams.redeemEnableTime)).utc();
Expand All @@ -86,10 +83,10 @@ export const renderCL4RParams = (CL4RParams: ICL4RParams) => {
<div>Start Time</div><div>{activationTime.format("h:mm A [UTC] on MMMM Do, YYYY")}</div>
<div>End Time</div><div>{endTime.format("h:mm A [UTC] on MMMM Do, YYYY")}</div>
<div>Redeem Enable Time</div><div>{`${redeemEnableTime.format("h:mm A [UTC] on MMMM Do, YYYY")} ${redeemEnableTime.isSameOrBefore(moment()) ? "(redeemable)" : "(not redeemable)"}`}</div>
<div>Batch Time</div><div>{`${secondsToDays(CL4RParams.batchTime).toFixed(2)} days`}</div>
<div>Batch Time</div><div>{humanizeDuration(CL4RParams.batchTime * 1000)}</div>
<div>Max Locking Batches</div><div>{CL4RParams.maxLockingBatches}</div>
<div>Batches Index Cap</div><div>{CL4RParams.batchesIndexCap}</div>
<div>Reputation Reward Const A</div><div>{`${numberWithCommas(new Decimal(realMathToBN(new BN(CL4RParams.repRewardConstA)).toString()).div(new Decimal(WEI)).toFixed(2))} REP`}</div>
<div>Reputation Reward Const A</div><div>{formatTokens(toWei(new Decimal(realMathToBN(new BN(CL4RParams.repRewardConstA)).toString()).div(new Decimal(WEI)).toNumber()), "REP")}</div>
<div>Reputation Reward Const B</div><div>{new Decimal(realMathToNumber(new BN(CL4RParams.repRewardConstB)).toString()).toFixed(2)}</div>
<div>Agreement Hash</div><div>{CL4RParams.agreementHash}</div>
</React.Fragment>);
Expand Down
4 changes: 2 additions & 2 deletions src/components/Scheme/CL4R/LockRow.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import BN from "bn.js";
import classNames from "classnames";
import { formatTokens, numberWithCommas } from "lib/util";
import { formatTokens } from "lib/util";
import moment from "moment-timezone";
import * as React from "react";
import * as css from "./LockRow.scss";
Expand Down Expand Up @@ -47,7 +47,7 @@ const LockRow = (props: IProps) => {
return (
<tr className={css.row}>
<td>{lockingBatch + 1}</td>
<td>{`${numberWithCommas(formatTokens(new BN(lockData.amount)))} ${schemeParams.tokenSymbol}`}</td>
<td>{formatTokens(new BN(lockData.amount), schemeParams.tokenSymbol)}</td>
<td>{lockData.period} Periods</td>
<td>{!lockData.released ? <span>{releasable.format("DD.MM.YYYY HH:mm")}</span> :
<div className={css.releasedLabel}>
Expand Down
16 changes: 8 additions & 8 deletions src/components/Scheme/CL4R/PeriodRow.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as React from "react";
import * as css from "./PeriodRow.scss";
import { getBatchIndexesRedeemed, getLockingBatch, ICL4RLock, ICL4RParams } from "./CL4RHelper";
import { formatTokens, numberWithCommas, WEI } from "lib/util";
import { formatTokens, toWei, WEI } from "lib/util";
import { CL4RScheme } from "@daostack/arc.js";
import Decimal from "decimal.js";
import BN from "bn.js";
Expand All @@ -19,15 +19,15 @@ interface IProps {

const PeriodRow = (props: IProps) => {
const { lockData, schemeParams, period, currentLockingBatch, isLockingEnded, redeemableAmount, setRedeemableAmount } = props;
const [repuationRewardForLockings, setRepuationRewardForLockings] = React.useState("0.00");
const [repuationRewardForBatch, setRepuationRewardForBatch] = React.useState("0.00");
const [repuationRewardForLockings, setRepuationRewardForLockings] = React.useState(new Decimal(0));
const [repuationRewardForBatch, setRepuationRewardForBatch] = React.useState(new Decimal(0));
const lockingIds: Array<number> = [];
let isPeriodRedeemed = false;

React.useEffect(() => {
// The user can't redeem reputation from the current batch.
if (period < currentLockingBatch) {
setRedeemableAmount(redeemableAmount + Number(repuationRewardForLockings));
setRedeemableAmount(redeemableAmount + repuationRewardForLockings.toNumber());
}
}, [repuationRewardForLockings]);

Expand All @@ -50,22 +50,22 @@ const PeriodRow = (props: IProps) => {
React.useEffect(() => {
const getRepuationData = async () => {
const repuationRewardForBatch = (await props.cl4rScheme.getRepuationRewardForBatch(schemeParams.repRewardConstA, schemeParams.repRewardConstB, period));
setRepuationRewardForBatch(repuationRewardForBatch.div(new Decimal(WEI)).toFixed(2));
setRepuationRewardForBatch(repuationRewardForBatch.div(new Decimal(WEI)));
const repuationRewardForLockings = await props.cl4rScheme.getReputationRewardForLockingIds(lockingIds, period, repuationRewardForBatch);
setRepuationRewardForLockings(repuationRewardForLockings.div(new Decimal(WEI)).toFixed(2));
setRepuationRewardForLockings(repuationRewardForLockings.div(new Decimal(WEI)));
};
getRepuationData();
}, [period, lockData]);

const inProgress = currentLockingBatch === period && !isLockingEnded;

const reputationToReceive = isPeriodRedeemed ? <div className={css.redeemedLabel}>Redeemed</div> : `${numberWithCommas(repuationRewardForLockings)} REP`;
const reputationToReceive = isPeriodRedeemed ? <div className={css.redeemedLabel}>Redeemed</div> : formatTokens(toWei(repuationRewardForLockings.toNumber()), "REP");

return (
<tr className={css.row}>
<td>{period + 1}</td>
<td>{formatTokens(youLocked, schemeParams.tokenSymbol)}</td>
<td>{`${numberWithCommas(repuationRewardForBatch)} REP`}</td>
<td>{formatTokens(toWei(repuationRewardForBatch.toNumber()), "REP")}</td>
<td>{inProgress ? <span className={css.inProgressLabel}>In Progress</span> : reputationToReceive}</td>
</tr>
);
Expand Down
8 changes: 0 additions & 8 deletions src/lib/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -821,14 +821,6 @@ export const getContractName = (address: string, daoAddress: string): string =>
}
};

/**
* Given a number adds comma if necessary
* @param {string | number} num
*/
export const numberWithCommas = (num: string | number): string => {
return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
};

export const realMathToNumber = (t: BN): number => {
const REAL_FBITS = 40;
const fraction = t.maskn(REAL_FBITS).toNumber() / Math.pow(2, REAL_FBITS);
Expand Down

0 comments on commit 63b9441

Please sign in to comment.