diff --git a/.env b/.env
new file mode 100644
index 0000000..633a3c5
--- /dev/null
+++ b/.env
@@ -0,0 +1 @@
+SKIP_PREFLIGHT_CHECK = true
diff --git a/README.md b/README.md
index 8f76915..414ce8f 100644
--- a/README.md
+++ b/README.md
@@ -18,7 +18,7 @@ yarn
1. clone repository and install packages
```sh
- git clone https://github.dev/OmniFlix/insync.git
+ git clone https://github.com/OmniFlix/insync.git
cd insync
yarn
```
@@ -33,7 +33,7 @@ yarn
export const config = {
RPC_URL: 'https://rpc.flixnet.omniflix.network',
REST_URL: 'https://rest.flixnet.omniflix.network',
- EXPLORER_URL: 'https://explorer.omniflix.network',
+ EXPLORER_URL: 'https://www.mintscan.io/omniflix',
STAKING_URL: 'https://flix.omniflix.co/stake',
NETWORK_NAME: 'OmniFlix',
NETWORK_TYPE: 'testnet',
diff --git a/config-overrides.js b/config-overrides.js
new file mode 100644
index 0000000..c3b47e2
--- /dev/null
+++ b/config-overrides.js
@@ -0,0 +1,25 @@
+const webpack = require('webpack');
+
+module.exports = function override (config, env) {
+ config.resolve.fallback = {
+ stream: require.resolve('stream-browserify'),
+ crypto: require.resolve('crypto-browserify'),
+ process: require.resolve('process/browser'),
+ buffer: require.resolve('buffer'),
+ levenary: false,
+ vm: false,
+ };
+ config.resolve.extensions = [...config.resolve.extensions, '.ts', '.js'];
+ config.plugins = [
+ ...config.plugins,
+ new webpack.ProvidePlugin({
+ Buffer: ['buffer', 'Buffer'],
+ }),
+ new webpack.ProvidePlugin({
+ process: 'process/browser',
+ }),
+ ];
+ config.ignoreWarnings = [/Failed to parse source map/];
+
+ return config;
+};
diff --git a/package.json b/package.json
index 91d546b..ca80d1d 100644
--- a/package.json
+++ b/package.json
@@ -6,40 +6,53 @@
"license": "MIT",
"private": true,
"dependencies": {
- "@cosmjs/amino": "^0.26.5",
- "@cosmjs/proto-signing": "^0.26.5",
- "@cosmjs/stargate": "^0.26.5",
- "@cosmostation/cosmos-client": "^0.0.1",
+ "@cosmjs/amino": "0.32.2",
+ "@cosmjs/launchpad": "0.27.1",
+ "@cosmjs/proto-signing": "0.32.2",
+ "@cosmjs/stargate": "0.32.2",
+ "@cosmostation/cosmos-client": "0.0.5",
"@cosmostation/extension-client": "^0.1.7",
+ "@emotion/react": "^11.11.3",
"@material-ui/core": "^4.11.3",
"@material-ui/icons": "^4.11.2",
"@material-ui/lab": "^4.0.0-alpha.58",
- "classnames": "^2.2.6",
+ "@redux-devtools/extension": "^3.3.0",
+ "buffer": "^6.0.3",
+ "classnames": "2.5.1",
+ "crypto-browserify": "^3.12.0",
"history": "^5.0.0",
"js-base64": "^3.6.0",
"latest": "^0.2.0",
"long": "^5.2.0",
- "moment": "^2.29.1",
+ "moment": "2.30.1",
"mui-datatables": "^3.7.7",
+ "process": "^0.11.10",
"prop-types": "^15.7.2",
- "react": "^16.12.0",
- "react-dom": "^16.13.1",
- "react-redux": "^7.2.0",
- "react-router": "^5.2.0",
- "react-router-dom": "^5.2.0",
- "react-scripts": "3.4.0",
- "redux": "^4.0.5",
- "redux-devtools-extension": "^2.13.8",
- "redux-thunk": "^2.3.0"
+ "react": "18.2.0",
+ "react-app-rewired": "^2.2.1",
+ "react-dom": "18.2.0",
+ "react-redux": "9.1.0",
+ "react-router": "6.22.0",
+ "react-router-dom": "6.22.0",
+ "react-scripts": "5.0.1",
+ "redux": "5.0.1",
+ "redux-thunk": "^2.3.0",
+ "stream-browserify": "^3.0.0",
+ "typescript": "^5.3.3",
+ "web-vitals": "^3.5.2",
+ "webpack": "^5.89.0"
},
"scripts": {
- "start": "react-scripts start",
- "build": "react-scripts build",
- "test": "react-scripts test",
- "eject": "react-scripts eject"
+ "start": "react-app-rewired start",
+ "build": "react-app-rewired build",
+ "test": "react-app-rewired test",
+ "eject": "react-app-rewired eject"
},
"devDependencies": {
- "@cosmjs/launchpad": "^0.26.5",
+ "@babel/core": "7.23.2",
+ "@babel/eslint-parser": "7.22.15",
+ "@babel/plugin-proposal-private-property-in-object": "7.21.11",
+ "@babel/preset-env": "7.23.2",
"axios": "^0.21.1",
"env-cmd": "^10.1.0",
"eslint": "^6.8.0",
@@ -50,6 +63,12 @@
"eslint-plugin-react": "^7.18.3",
"eslint-plugin-standard": "^4.0.1"
},
+ "eslintConfig": {
+ "extends": [
+ "react-app",
+ "react-app/jest"
+ ]
+ },
"browserslist": {
"production": [
">0.2%",
diff --git a/public/favicon.ico b/public/favicon.ico
index 65869ce..2790ce7 100644
Binary files a/public/favicon.ico and b/public/favicon.ico differ
diff --git a/src/Router.js b/src/Router.js
index 9475401..6214abf 100644
--- a/src/Router.js
+++ b/src/Router.js
@@ -1,5 +1,5 @@
import React from 'react';
-import { Route, Switch } from 'react-router-dom';
+import { Route, Routes } from 'react-router-dom';
import Home from './containers/Home';
import Stake from './containers/Stake';
import Proposals from './containers/Proposals';
@@ -23,19 +23,19 @@ const Router = () => {
return (
-
+
{routes.map((route) =>
}
path={route.path}/>,
)}
}
path="*"/>
-
+
);
diff --git a/src/actions/accounts/index.js b/src/actions/accounts/index.js
index 9a38ece..7b89ee8 100644
--- a/src/actions/accounts/index.js
+++ b/src/actions/accounts/index.js
@@ -149,7 +149,7 @@ export const fetchVestingBalance = (address) => (dispatch) => {
},
})
.then((res) => {
- dispatch(fetchVestingBalanceSuccess(res.data && res.data.result));
+ dispatch(fetchVestingBalanceSuccess(res.data && res.data.balances));
})
.catch((error) => {
dispatch(fetchVestingBalanceError(
diff --git a/src/actions/stake.js b/src/actions/stake.js
index 89c31af..b0d678c 100644
--- a/src/actions/stake.js
+++ b/src/actions/stake.js
@@ -1,7 +1,13 @@
import {
+ APR_FETCH_ERROR,
+ APR_FETCH_IN_PROGRESS,
+ APR_FETCH_SUCCESS,
CLAIM_REWARDS_DIALOG_HIDE,
CLAIM_REWARDS_DIALOG_SHOW,
CLAIM_REWARDS_VALIDATOR_SET,
+ CLAIM_DELEGATE_DIALOG_SHOW,
+ CLAIM_DELEGATE_DIALOG_HIDE,
+ CLAIM_DELEGATE_VALIDATOR_SET,
DELEGATE_DIALOG_HIDE,
DELEGATE_DIALOG_SHOW,
DELEGATE_FAILED_DIALOG_HIDE,
@@ -13,6 +19,9 @@ import {
DELEGATED_VALIDATORS_FETCH_ERROR,
DELEGATED_VALIDATORS_FETCH_IN_PROGRESS,
DELEGATED_VALIDATORS_FETCH_SUCCESS,
+ INACTIVE_VALIDATORS_FETCH_ERROR,
+ INACTIVE_VALIDATORS_FETCH_IN_PROGRESS,
+ INACTIVE_VALIDATORS_FETCH_SUCCESS,
SEARCH_LIST_SET,
TO_VALIDATOR_SET,
TOKENS_SET,
@@ -26,10 +35,21 @@ import {
VALIDATORS_FETCH_ERROR,
VALIDATORS_FETCH_IN_PROGRESS,
VALIDATORS_FETCH_SUCCESS,
+ SELECTED_MULTI_VALIDATORS,
} from '../constants/stake';
import Axios from 'axios';
-import { getDelegatedValidatorsURL, getValidatorURL, validatorImageURL, VALIDATORS_LIST_URL } from '../constants/url';
+import {
+ getDelegatedValidatorsURL,
+ getValidatorURL,
+ INACTIVE_VALIDATORS_UNBONDING_URL,
+ INACTIVE_VALIDATORS_URL,
+ validatorImageURL,
+ VALIDATORS_LIST_URL,
+} from '../constants/url';
import { config } from '../config';
+import { calculateNominalAPR, calculateRealAPR, getBlocksPerYearReal, getParams } from '../utils/aprCalculation';
+
+const axios = require('axios').default;
const fetchValidatorsInProgress = () => {
return {
@@ -60,7 +80,7 @@ export const getValidators = (cb) => (dispatch) => {
})
.then((res) => {
dispatch(fetchValidatorsSuccess(res.data && res.data.validators));
- cb(res.data && res.data.result);
+ cb(res.data && res.data.validators);
})
.catch((error) => {
dispatch(fetchValidatorsError(
@@ -183,7 +203,7 @@ export const getValidatorDetails = (address, cb) => (dispatch) => {
})
.then((res) => {
dispatch(fetchValidatorSuccess(res.data && res.data.validators));
- cb(res.data && res.data.result);
+ cb(res.data && res.data.validators);
})
.catch((error) => {
dispatch(fetchValidatorError(
@@ -258,6 +278,25 @@ export const setClaimRewardsValidator = (value) => {
};
};
+export const showClaimDelegateDialog = () => {
+ return {
+ type: CLAIM_DELEGATE_DIALOG_SHOW,
+ };
+};
+
+export const hideClaimDelegateDialog = () => {
+ return {
+ type: CLAIM_DELEGATE_DIALOG_HIDE,
+ };
+};
+
+export const setClaimDelegateValidator = (value) => {
+ return {
+ type: CLAIM_DELEGATE_VALIDATOR_SET,
+ value,
+ };
+};
+
const fetchValidatorImageInProgress = () => {
return {
type: VALIDATOR_IMAGE_FETCH_IN_PROGRESS,
@@ -307,3 +346,115 @@ export const fetchValidatorImage = (id) => (dispatch) => {
));
});
};
+
+const fetchInActiveValidatorsInProgress = () => {
+ return {
+ type: INACTIVE_VALIDATORS_FETCH_IN_PROGRESS,
+ };
+};
+
+const fetchInActiveValidatorsSuccess = (list) => {
+ return {
+ type: INACTIVE_VALIDATORS_FETCH_SUCCESS,
+ list,
+ };
+};
+
+const fetchInActiveValidatorsError = (message) => {
+ return {
+ type: INACTIVE_VALIDATORS_FETCH_ERROR,
+ };
+};
+
+export const getInActiveValidators = (cb) => (dispatch) => {
+ dispatch(fetchInActiveValidatorsInProgress());
+ (async () => {
+ try {
+ const result = await Axios.get(INACTIVE_VALIDATORS_URL, {
+ headers: {
+ Accept: 'application/json, text/plain, */*',
+ Connection: 'keep-alive',
+ },
+ });
+ const unBondingResult = await Axios.get(INACTIVE_VALIDATORS_UNBONDING_URL, {
+ headers: {
+ Accept: 'application/json, text/plain, */*',
+ Connection: 'keep-alive',
+ },
+ });
+ const updatedResult = [...result.data && result.data.validators, ...unBondingResult.data && unBondingResult.data.validators];
+ dispatch(fetchInActiveValidatorsSuccess(updatedResult));
+ cb(updatedResult);
+ } catch (error) {
+ dispatch(fetchInActiveValidatorsError(
+ error.response &&
+ error.response.data &&
+ error.response.data.message
+ ? error.response.data.message
+ : 'Failed!',
+ ));
+ cb(null);
+ }
+ })();
+};
+
+const fetchAPRInProgress = () => {
+ return {
+ type: APR_FETCH_IN_PROGRESS,
+ };
+};
+
+export const fetchAPRSuccess = (nominalAPR, actualAPR) => {
+ return {
+ type: APR_FETCH_SUCCESS,
+ nominalAPR,
+ actualAPR,
+ };
+};
+
+const fetchAPRError = (message) => {
+ return {
+ type: APR_FETCH_ERROR,
+ message,
+ };
+};
+
+export const fetchAPR = () => (dispatch) => {
+ dispatch(fetchAPRInProgress());
+ (async () => {
+ try {
+ const apiUrl = config.REST_URL;
+ const lcdApi = axios.create({
+ baseURL: apiUrl,
+ headers: {
+ 'Content-Type': 'application/json; charset=utf-8',
+ Accept: 'application/json',
+ },
+ timeout: 10000,
+ });
+
+ const params = await getParams(lcdApi);
+ const blocksYearReal = await getBlocksPerYearReal(lcdApi);
+ const nominalAPR = calculateNominalAPR(params);
+ const actualAPR = calculateRealAPR(params, nominalAPR, blocksYearReal);
+
+ dispatch(fetchAPRSuccess((nominalAPR * 100), (actualAPR * 100)));
+ } catch (error) {
+ dispatch(fetchAPRError(
+ error.response &&
+ error.response.data &&
+ error.response.data.message
+ ? error.response.data.message
+ : error,
+ ));
+ return null;
+ }
+ })();
+};
+
+export const selectMultiValidators = (value) => {
+ return {
+ type: SELECTED_MULTI_VALIDATORS,
+ value,
+ };
+};
diff --git a/src/app.css b/src/app.css
index b8c7397..f96ef03 100644
--- a/src/app.css
+++ b/src/app.css
@@ -178,3 +178,33 @@ html::-webkit-scrollbar-thumb,
margin: 10px;
}
}
+
+@keyframes fadeInAnimation {
+ from {
+ opacity: 0;
+ }
+
+ to {
+ opacity: 1;
+ }
+}
+
+.stake .stake_content,
+.proposals .proposals_content,
+.home .card {
+ animation: fadeInAnimation ease-in-out 1s;
+}
+
+@keyframes dialogOpen {
+ from {
+ transform: scale(0.5);
+ }
+
+ to {
+ transform: scale(1);
+ }
+}
+
+.dialog {
+ animation: dialogOpen 0.1s;
+}
diff --git a/src/components/BackButton/index.js b/src/components/BackButton/index.js
index a91dcaa..31b9f10 100644
--- a/src/components/BackButton/index.js
+++ b/src/components/BackButton/index.js
@@ -3,7 +3,7 @@ import backIcon from '../../assets/back.png';
import { IconButton } from '@material-ui/core';
import * as PropTypes from 'prop-types';
import './index.css';
-import { withRouter } from 'react-router-dom';
+import withRouter from '../WithRouter';
const BackButton = (props) => {
const onClick = () => {
@@ -13,7 +13,7 @@ const BackButton = (props) => {
return;
}
- props.history.goBack();
+ props.router.navigate(-1);
};
return (
@@ -26,9 +26,9 @@ const BackButton = (props) => {
};
BackButton.propTypes = {
- history: PropTypes.shape({
- goBack: PropTypes.func.isRequired,
- }).isRequired,
+ router: PropTypes.shape({
+ navigate: PropTypes.func.isRequired,
+ }),
onClick: PropTypes.func,
};
diff --git a/src/components/WithRouter.js b/src/components/WithRouter.js
new file mode 100644
index 0000000..f655641
--- /dev/null
+++ b/src/components/WithRouter.js
@@ -0,0 +1,25 @@
+import React from 'react';
+import { useLocation, useNavigate, useParams } from 'react-router-dom';
+
+function withRouter (Component) {
+ function ComponentWithRouterProp (props) {
+ const location = useLocation();
+ const navigate = useNavigate();
+ const params = useParams();
+
+ return (
+ // eslint-disable-next-line react/react-in-jsx-scope
+
+ );
+ }
+
+ return ComponentWithRouterProp;
+}
+
+export default withRouter;
diff --git a/src/constants/stake.js b/src/constants/stake.js
index fac7ed3..00ce4fc 100644
--- a/src/constants/stake.js
+++ b/src/constants/stake.js
@@ -31,9 +31,22 @@ export const DELEGATED_VALIDATORS_FETCH_ERROR = 'DELEGATED_VALIDATORS_FETCH_ERRO
export const CLAIM_REWARDS_DIALOG_SHOW = 'CLAIM_REWARDS_DIALOG_SHOW';
export const CLAIM_REWARDS_DIALOG_HIDE = 'CLAIM_REWARDS_DIALOG_HIDE';
-
export const CLAIM_REWARDS_VALIDATOR_SET = 'CLAIM_REWARDS_VALIDATOR_SET';
+export const CLAIM_DELEGATE_DIALOG_SHOW = 'CLAIM_DELEGATE_DIALOG_SHOW';
+export const CLAIM_DELEGATE_DIALOG_HIDE = 'CLAIM_DELEGATE_DIALOG_HIDE';
+export const CLAIM_DELEGATE_VALIDATOR_SET = 'CLAIM_DELEGATE_VALIDATOR_SET';
+
export const VALIDATOR_IMAGE_FETCH_IN_PROGRESS = 'VALIDATOR_IMAGE_FETCH_IN_PROGRESS';
export const VALIDATOR_IMAGE_FETCH_SUCCESS = 'VALIDATOR_IMAGE_FETCH_SUCCESS';
export const VALIDATOR_IMAGE_FETCH_ERROR = 'VALIDATOR_IMAGE_FETCH_ERROR';
+
+export const INACTIVE_VALIDATORS_FETCH_IN_PROGRESS = 'INACTIVE_VALIDATORS_FETCH_IN_PROGRESS';
+export const INACTIVE_VALIDATORS_FETCH_SUCCESS = 'INACTIVE_VALIDATORS_FETCH_SUCCESS';
+export const INACTIVE_VALIDATORS_FETCH_ERROR = 'INACTIVE_VALIDATORS_FETCH_ERROR';
+
+export const APR_FETCH_IN_PROGRESS = 'APR_FETCH_IN_PROGRESS';
+export const APR_FETCH_SUCCESS = 'APR_FETCH_SUCCESS';
+export const APR_FETCH_ERROR = 'APR_FETCH_ERROR';
+
+export const SELECTED_MULTI_VALIDATORS = 'SELECTED_MULTI_VALIDATORS';
diff --git a/src/constants/url.js b/src/constants/url.js
index 5e2df3e..a872d3b 100644
--- a/src/constants/url.js
+++ b/src/constants/url.js
@@ -14,6 +14,8 @@ export const urlFetchVoteDetails = (proposalId, address) => `${REST_URL}/cosmos/
export const VALIDATORS_LIST_URL = `${REST_URL}/cosmos/staking/v1beta1/validators?pagination.limit=1000`;
export const getValidatorURL = (address) => `${REST_URL}/cosmos/staking/v1beta1/validators/${address}`;
export const PROPOSALS_LIST_URL = `${REST_URL}/cosmos/gov/v1beta1/proposals?pagination.limit=1000`;
+export const INACTIVE_VALIDATORS_URL = `${REST_URL}/cosmos/staking/v1beta1/validators?pagination.limit=1000&status=BOND_STATUS_UNBONDED`;
+export const INACTIVE_VALIDATORS_UNBONDING_URL = `${REST_URL}/cosmos/staking/v1beta1/validators?pagination.limit=1000&status=BOND_STATUS_UNBONDING`;
export const getDelegatedValidatorsURL = (address) => `${REST_URL}/cosmos/staking/v1beta1/delegators/${address}/validators`;
export const urlFetchProposalVotes = (id) => `${REST_URL}/cosmos/gov/v1beta1/proposals/${id}/votes`;
export const urlFetchTallyDetails = (id) => `${REST_URL}/cosmos/gov/v1beta1/proposals/${id}/tally`;
diff --git a/src/containers/Home/ClaimDialog/ClaimDelegateDialog.js b/src/containers/Home/ClaimDialog/ClaimDelegateDialog.js
new file mode 100644
index 0000000..72050bf
--- /dev/null
+++ b/src/containers/Home/ClaimDialog/ClaimDelegateDialog.js
@@ -0,0 +1,248 @@
+import React, { useState } from 'react';
+import { Button, Dialog, DialogActions, DialogContent } from '@material-ui/core';
+import * as PropTypes from 'prop-types';
+import {
+ hideClaimDelegateDialog,
+ setTokens,
+ showDelegateFailedDialog,
+ showDelegateProcessingDialog,
+ showDelegateSuccessDialog,
+} from '../../../actions/stake';
+import { connect } from 'react-redux';
+import '../../Stake/DelegateDialog/index.css';
+import { cosmoStationSign, signTxAndBroadcast } from '../../../helper';
+import { showMessage } from '../../../actions/snackbar';
+import { fetchRewards, fetchVestingBalance, getBalance } from '../../../actions/accounts';
+import { config } from '../../../config';
+import variables from '../../../utils/variables';
+import CircularProgress from '../../../components/CircularProgress';
+import { gas } from '../../../defaultGasValues';
+import ClaimDelegateValidatorsSelectField from './ClaimDelegateValidatorSelectField';
+
+const ClaimDelegateDialog = (props) => {
+ const [inProgress, setInProgress] = useState(false);
+
+ const handleClaimAll = () => {
+ setInProgress(true);
+ let gasValue = gas.claim_reward + gas.delegate;
+ let count = 0;
+ if (props.rewards && props.rewards.rewards && props.rewards.rewards.length > 1) {
+ props.rewards.rewards.map((item) => {
+ const tokens = item && item.reward && item.reward.length &&
+ item.reward.filter((val) => val.amount > gasValue * config.GAS_PRICE_STEP_AVERAGE);
+ if (tokens) {
+ count += tokens.length;
+ }
+ return null;
+ });
+ }
+ if (count) {
+ gasValue = count * gasValue / 1.1 + gasValue;
+ }
+
+ const updatedTx = {
+ msgs: [],
+ fee: {
+ amount: [{
+ amount: String(gasValue * config.GAS_PRICE_STEP_AVERAGE),
+ denom: config.COIN_MINIMAL_DENOM,
+ }],
+ gas: String(gasValue),
+ },
+ memo: '',
+ };
+ if (props.rewards && props.rewards.rewards &&
+ props.rewards.rewards.length) {
+ props.rewards.rewards.map((item) => {
+ let tokens = item && item.reward && item.reward.length &&
+ item.reward.find((val) => val.denom === config.COIN_MINIMAL_DENOM);
+ tokens = tokens && tokens.amount;
+ if (tokens && tokens > ((gas.claim_reward + gas.delegate) * config.GAS_PRICE_STEP_AVERAGE)) {
+ updatedTx.msgs.push({
+ typeUrl: '/cosmos.distribution.v1beta1.MsgWithdrawDelegatorReward',
+ value: {
+ delegatorAddress: props.address,
+ validatorAddress: item.validator_address,
+ },
+ }, {
+ typeUrl: '/cosmos.staking.v1beta1.MsgDelegate',
+ value: {
+ delegatorAddress: props.address,
+ validatorAddress: item.validator_address,
+ amount: {
+ amount: String(Math.floor(Number(tokens))),
+ denom: config.COIN_MINIMAL_DENOM,
+ },
+ },
+ });
+ }
+ return null;
+ });
+ }
+
+ if (localStorage.getItem('of_co_wallet') === 'cosmostation') {
+ cosmoStationSign(updatedTx, props.address, handleFetch);
+ return;
+ }
+
+ signTxAndBroadcast(updatedTx, props.address, handleFetch);
+ };
+
+ const handleFetch = (error, result) => {
+ setInProgress(false);
+ if (error) {
+ if (error.indexOf('not yet found on the chain') > -1) {
+ props.pendingDialog();
+ return;
+ }
+ props.failedDialog();
+ props.showMessage(error);
+ return;
+ }
+ if (result) {
+ props.setTokens(tokens);
+ props.successDialog(result.transactionHash);
+ props.fetchRewards(props.address);
+ props.getBalance(props.address);
+ props.fetchVestingBalance(props.address);
+ }
+ };
+
+ const handleClaim = () => {
+ setInProgress(true);
+ const updatedTx = {
+ msgs: [{
+ typeUrl: '/cosmos.distribution.v1beta1.MsgWithdrawDelegatorReward',
+ value: {
+ delegatorAddress: props.address,
+ validatorAddress: props.value,
+ },
+ }, {
+ typeUrl: '/cosmos.staking.v1beta1.MsgDelegate',
+ value: {
+ delegatorAddress: props.address,
+ validatorAddress: props.value,
+ amount: {
+ amount: String(Math.floor(Number(delegateableTokesn))),
+ denom: config.COIN_MINIMAL_DENOM,
+ },
+ },
+ }],
+ fee: {
+ amount: [{
+ amount: String((gas.claim_reward + gas.delegate) * config.GAS_PRICE_STEP_AVERAGE),
+ denom: config.COIN_MINIMAL_DENOM,
+ }],
+ gas: String(gas.claim_reward + gas.delegate),
+ },
+ memo: '',
+ };
+
+ if (localStorage.getItem('of_co_wallet') === 'cosmostation') {
+ cosmoStationSign(updatedTx, props.address, handleFetch);
+ return;
+ }
+
+ signTxAndBroadcast(updatedTx, props.address, handleFetch);
+ };
+
+ const rewards = props.rewards && props.rewards.rewards &&
+ props.rewards.rewards.length &&
+ props.rewards.rewards.filter((value) => value.validator_address === props.value);
+
+ let tokens = rewards && rewards.length && rewards[0] && rewards[0].reward &&
+ rewards[0].reward.length && rewards[0].reward.find((val) => val.denom === config.COIN_MINIMAL_DENOM);
+ const delegateableTokesn = tokens && tokens.amount;
+ tokens = tokens && tokens.amount ? tokens.amount / 10 ** config.COIN_DECIMALS : 0;
+
+ if (props.value === 'all' && props.rewards && props.rewards.rewards &&
+ props.rewards.rewards.length) {
+ const gasValue = (gas.claim_reward + gas.delegate) * config.GAS_PRICE_STEP_AVERAGE;
+ let total = 0;
+
+ props.rewards.rewards.map((value) => {
+ let rewards = value.reward && value.reward.length &&
+ value.reward.find((val) => val.denom === config.COIN_MINIMAL_DENOM);
+ rewards = rewards && rewards.amount && rewards.amount > gasValue ? rewards.amount / 10 ** config.COIN_DECIMALS : 0;
+ total = rewards + total;
+
+ return total;
+ });
+ tokens = total;
+ }
+
+ const disable = props.value === 'none' || inProgress;
+
+ return (
+
+ );
+};
+
+ClaimDelegateDialog.propTypes = {
+ failedDialog: PropTypes.func.isRequired,
+ fetchRewards: PropTypes.func.isRequired,
+ fetchVestingBalance: PropTypes.func.isRequired,
+ getBalance: PropTypes.func.isRequired,
+ handleClose: PropTypes.func.isRequired,
+ lang: PropTypes.string.isRequired,
+ open: PropTypes.bool.isRequired,
+ pendingDialog: PropTypes.func.isRequired,
+ rewards: PropTypes.shape({
+ rewards: PropTypes.array,
+ total: PropTypes.array,
+ }).isRequired,
+ setTokens: PropTypes.func.isRequired,
+ showMessage: PropTypes.func.isRequired,
+ successDialog: PropTypes.func.isRequired,
+ value: PropTypes.string.isRequired,
+ address: PropTypes.string,
+};
+
+const stateToProps = (state) => {
+ return {
+ address: state.accounts.address.value,
+ lang: state.language,
+ open: state.stake.claimDelegateDialog.open,
+ value: state.stake.claimDelegateDialog.validator,
+ rewards: state.accounts.rewards.result,
+ };
+};
+
+const actionToProps = {
+ handleClose: hideClaimDelegateDialog,
+ failedDialog: showDelegateFailedDialog,
+ successDialog: showDelegateSuccessDialog,
+ pendingDialog: showDelegateProcessingDialog,
+ getBalance,
+ fetchVestingBalance,
+ showMessage,
+ fetchRewards,
+ setTokens,
+};
+
+export default connect(stateToProps, actionToProps)(ClaimDelegateDialog);
diff --git a/src/containers/Home/ClaimDialog/ClaimDelegateValidatorSelectField.js b/src/containers/Home/ClaimDialog/ClaimDelegateValidatorSelectField.js
new file mode 100644
index 0000000..bbc0a31
--- /dev/null
+++ b/src/containers/Home/ClaimDialog/ClaimDelegateValidatorSelectField.js
@@ -0,0 +1,136 @@
+import React from 'react';
+import * as PropTypes from 'prop-types';
+import { connect } from 'react-redux';
+import SelectField from '../../../components/SelectField/WithChildren';
+import { setClaimDelegateValidator } from '../../../actions/stake';
+import { MenuItem } from '@material-ui/core';
+import { config } from '../../../config';
+import { gas } from '../../../defaultGasValues';
+
+const colors = ['#0023DA', '#C9387E', '#EC2C00', '#80E3F2',
+ '#E86FC5', '#1F3278', '#FFE761', '#7041B9'];
+
+const ClaimDelegateValidatorSelectField = (props) => {
+ const gasValue = (gas.claim_reward + gas.delegate) * config.GAS_PRICE_STEP_AVERAGE;
+ const handleChange = (value) => {
+ if (props.value === value) {
+ return;
+ }
+
+ props.onChange(value);
+ };
+
+ let total = 0;
+ const totalRewards = props.rewards && props.rewards.rewards &&
+ props.rewards.rewards.length && props.rewards.rewards.map((value) => {
+ let rewards = value.reward && value.reward.length &&
+ value.reward.find((val) => val.denom === config.COIN_MINIMAL_DENOM);
+ rewards = rewards && rewards.amount && rewards.amount > gasValue ? rewards.amount / 10 ** config.COIN_DECIMALS : 0;
+ if (rewards) {
+ total = rewards + total;
+ return total;
+ }
+ return null;
+ });
+
+ return (
+
+
+ {props.rewards && props.rewards.rewards &&
+ props.rewards.rewards.length &&
+ props.rewards.rewards.map((item, index) => {
+ const validator = item && item.validator_address && props.validatorList && props.validatorList.length &&
+ props.validatorList.filter((value) => value.operator_address === item.validator_address);
+
+ const image = validator && validator.length && validator[0] &&
+ validator[0].description && validator[0].description.identity &&
+ props.validatorImages && props.validatorImages.length &&
+ props.validatorImages.filter((value) => value._id === validator[0].description.identity.toString());
+
+ let rewards = item.reward && item.reward.length &&
+ item.reward.find((val) => val.denom === config.COIN_MINIMAL_DENOM);
+ rewards = rewards && rewards.amount && rewards.amount > gasValue ? rewards.amount / 10 ** config.COIN_DECIMALS : 0;
+
+ return (
+ rewards && rewards > 0.000001
+ ? : null
+ );
+ },
+ )}
+ {totalRewards && totalRewards.length &&
+ }
+
+ );
+};
+
+ClaimDelegateValidatorSelectField.propTypes = {
+ rewards: PropTypes.shape({
+ rewards: PropTypes.array,
+ total: PropTypes.array,
+ }).isRequired,
+ validatorImages: PropTypes.array.isRequired,
+ value: PropTypes.string.isRequired,
+ onChange: PropTypes.func.isRequired,
+ inProgress: PropTypes.bool,
+ items: PropTypes.array,
+ validatorList: PropTypes.arrayOf(
+ PropTypes.shape({
+ operator_address: PropTypes.string,
+ status: PropTypes.number,
+ description: PropTypes.shape({
+ moniker: PropTypes.string,
+ }),
+ }),
+ ),
+};
+
+const stateToProps = (state) => {
+ return {
+ value: state.stake.claimDelegateDialog.validator,
+ rewards: state.accounts.rewards.result,
+ validatorList: state.stake.validators.list,
+ inProgress: state.accounts.rewards.inProgress,
+ validatorImages: state.stake.validators.images,
+ };
+};
+
+const actionToProps = {
+ onChange: setClaimDelegateValidator,
+};
+
+export default connect(stateToProps, actionToProps)(ClaimDelegateValidatorSelectField);
diff --git a/src/containers/Home/TokenDetails/Compound.js b/src/containers/Home/TokenDetails/Compound.js
new file mode 100644
index 0000000..80a0585
--- /dev/null
+++ b/src/containers/Home/TokenDetails/Compound.js
@@ -0,0 +1,50 @@
+import React from 'react';
+import { Button } from '@material-ui/core';
+import * as PropTypes from 'prop-types';
+import { connect } from 'react-redux';
+import variables from '../../../utils/variables';
+import { showClaimDelegateDialog } from '../../../actions/stake';
+import { showMessage } from '../../../actions/snackbar';
+
+const Compound = (props) => {
+ const handleClick = () => {
+ if (!props.address) {
+ props.showMessage(variables[props.lang]['connect_account']);
+ return;
+ }
+ props.handleOpen('Compound');
+ };
+
+ return (
+
+ );
+};
+
+Compound.propTypes = {
+ disable: PropTypes.bool.isRequired,
+ handleOpen: PropTypes.func.isRequired,
+ lang: PropTypes.string.isRequired,
+ showMessage: PropTypes.func.isRequired,
+ address: PropTypes.string,
+};
+
+const stateToProps = (state) => {
+ return {
+ address: state.accounts.address.value,
+ lang: state.language,
+ };
+};
+
+const actionToProps = {
+ handleOpen: showClaimDelegateDialog,
+ showMessage,
+
+};
+
+export default connect(stateToProps, actionToProps)(Compound);
diff --git a/src/containers/Home/TokenDetails/index.css b/src/containers/Home/TokenDetails/index.css
index d0b9bfa..8faf1ac 100644
--- a/src/containers/Home/TokenDetails/index.css
+++ b/src/containers/Home/TokenDetails/index.css
@@ -70,7 +70,7 @@
margin: 0 10px;
}
-@media (max-width: 1441px) {
+@media (max-width: 2000px) {
.token_details {
margin: 40px 0 0;
width: 100%;
diff --git a/src/containers/Home/TokenDetails/index.js b/src/containers/Home/TokenDetails/index.js
index 703c74f..79cc1ec 100644
--- a/src/containers/Home/TokenDetails/index.js
+++ b/src/containers/Home/TokenDetails/index.js
@@ -11,15 +11,18 @@ import StakeTokensButton from './StakeTokensButton';
import UnDelegateButton from './UnDelegateButton';
import ReDelegateButton from './ReDelegateButton';
import ClaimButton from './ClaimButton';
+// import Compound from './Compound';
import { config } from '../../../config';
+// import { gas } from '../../../defaultGasValues';
const TokenDetails = (props) => {
- const staked = props.delegations.reduce((accumulator, currentValue) => {
+ const staked = props.delegations && props.delegations.reduce((accumulator, currentValue) => {
return accumulator + Number(currentValue.balance.amount);
}, 0);
const balance = props.balance && props.balance.length && props.balance.find((val) => val.denom === config.COIN_MINIMAL_DENOM);
const available = (balance && balance.amount && Number(balance.amount));
let unStaked = 0;
+ props.unBondingDelegations && props.unBondingDelegations.length &&
props.unBondingDelegations.map((delegation) => {
delegation.entries && delegation.entries.length &&
delegation.entries.map((entry) => {
@@ -30,9 +33,13 @@ const TokenDetails = (props) => {
return null;
});
+ // const gasValue = (gas.claim_reward + gas.delegate) * config.GAS_PRICE_STEP_AVERAGE;
let rewards = props.rewards && props.rewards.total && props.rewards.total.length &&
props.rewards.total.find((val) => val.denom === config.COIN_MINIMAL_DENOM);
rewards = rewards && rewards.amount ? rewards.amount / 10 ** config.COIN_DECIMALS : 0;
+ // let tokens = props.rewards && props.rewards.total && props.rewards.total.length &&
+ // props.rewards.total.find((val) => val.amount > gasValue);
+ // tokens = tokens && tokens.amount ? tokens.amount / 10 ** config.COIN_DECIMALS : 0;
return (
@@ -64,6 +71,8 @@ const TokenDetails = (props) => {
+ {/* */}
+ {/* */}
@@ -73,6 +82,13 @@ const TokenDetails = (props) => {
{unStaked / (10 ** config.COIN_DECIMALS)}
+ {props.actualAPR
+ ?
+
{variables[props.lang]['staking_apr']}
+
+
{props.actualAPR.toFixed(2) + ' %'}
+
+
: null}
);
};
@@ -87,6 +103,7 @@ TokenDetails.propTypes = {
}).isRequired,
rewardsInProgress: PropTypes.bool.isRequired,
unBondingDelegationsInProgress: PropTypes.bool.isRequired,
+ actualAPR: PropTypes.number,
balance: PropTypes.arrayOf(
PropTypes.shape({
amount: PropTypes.any,
@@ -115,6 +132,7 @@ TokenDetails.propTypes = {
const stateToProps = (state) => {
return {
+ actualAPR: state.stake.apr.actualAPR,
delegations: state.accounts.delegations.result,
delegationsInProgress: state.accounts.delegations.inProgress,
balance: state.accounts.balance.result,
diff --git a/src/containers/Home/index.css b/src/containers/Home/index.css
index 60d9877..39f1865 100644
--- a/src/containers/Home/index.css
+++ b/src/containers/Home/index.css
@@ -159,19 +159,26 @@
.content_div .view_all {
background: #FFFFFF;
- border-radius: 50px;
+ border-radius: 30px;
font-family: 'Blinker', sans-serif;
font-weight: 600;
- font-size: 20px;
+ font-size: 18px;
line-height: 130%;
color: #000000;
- padding: 8px 20px;
+ padding: 9px 20px;
+ margin-left: 5px;
}
.content_div .view_all:hover {
background: #FFFFFF;
}
+@media (max-width: 2000px) {
+ .stake .stake_content .heading .buttons {
+ display: flex;
+ }
+}
+
@media (max-width: 1441px) {
.home .card {
flex-direction: column;
@@ -180,7 +187,7 @@
}
}
-@media (max-width: 769px) {
+@media (max-width: 770px) {
.home .card {
padding: 50px 20px;
}
diff --git a/src/containers/Home/index.js b/src/containers/Home/index.js
index 0b0ed1f..632075f 100644
--- a/src/containers/Home/index.js
+++ b/src/containers/Home/index.js
@@ -8,13 +8,15 @@ import DelegateDialog from '../Stake/DelegateDialog';
import SuccessDialog from '../Stake/DelegateDialog/SuccessDialog';
import UnSuccessDialog from '../Stake/DelegateDialog/UnSuccessDialog';
import ClaimDialog from './ClaimDialog';
+import ClaimDelegateDialog from './ClaimDialog/ClaimDelegateDialog';
import Table from '../Stake/Table';
import { Button } from '@material-ui/core';
import Cards from '../Proposals/Cards';
import ProposalDialog from '../Proposals/ProposalDialog';
-import { withRouter } from 'react-router';
import { connect } from 'react-redux';
import PendingDialog from '../Stake/DelegateDialog/PendingDialog';
+import MultiDelegateButton from '../Stake/MultiDelegateButton';
+import withRouter from '../../components/WithRouter';
class Home extends Component {
constructor (props) {
@@ -62,7 +64,7 @@ class Home extends Component {
}
handleRedirect (value) {
- this.props.history.push(value);
+ this.props.router.navigate(value);
}
render () {
@@ -88,15 +90,34 @@ class Home extends Component {
this.handleChange(2)}>
{variables[this.props.lang]['staked_validators']}
+ {this.props.delegatedValidatorList &&
+ this.props.delegatedValidatorList.length
+ ? ' (' + this.props.delegatedValidatorList.length + ')'
+ : null}
this.handleChange(1)}>
- {variables[this.props.lang]['all_validators']}
+ {variables[this.props.lang]['active_validators']}
+ {this.props.validatorList &&
+ this.props.validatorList.length
+ ? ' (' + this.props.validatorList.length + ')'
+ : null}
+
+
this.handleChange(3)}>
+ {variables[this.props.lang]['inactive_validators']}
+ {this.props.inActiveValidators &&
+ this.props.inActiveValidators.length
+ ? ' (' + this.props.inActiveValidators.length + ')'
+ : null}
+
+
+
+
+
-
@@ -127,21 +148,25 @@ class Home extends Component {
+
>
);
}
}
Home.propTypes = {
- history: PropTypes.shape({
- push: PropTypes.func.isRequired,
- }).isRequired,
+ delegatedValidatorList: PropTypes.array.isRequired,
+ inActiveValidators: PropTypes.array.isRequired,
lang: PropTypes.string.isRequired,
open: PropTypes.bool.isRequired,
proposals: PropTypes.array.isRequired,
+ validatorList: PropTypes.array.isRequired,
voteDetailsInProgress: PropTypes.bool.isRequired,
address: PropTypes.string,
proposalsInProgress: PropTypes.bool,
+ router: PropTypes.shape({
+ navigate: PropTypes.func.isRequired,
+ }),
};
const stateToProps = (state) => {
@@ -152,6 +177,9 @@ const stateToProps = (state) => {
proposals: state.proposals._.list,
proposalsInProgress: state.proposals._.inProgress,
voteDetailsInProgress: state.proposals.voteDetails.inProgress,
+ delegatedValidatorList: state.stake.delegatedValidators.list,
+ inActiveValidators: state.stake.inActiveValidators.list,
+ validatorList: state.stake.validators.list,
};
};
diff --git a/src/containers/NavBar/ConnectDialog/CosmostationConnectButton.js b/src/containers/NavBar/ConnectDialog/CosmostationConnectButton.js
index 919cbfb..f41b34b 100644
--- a/src/containers/NavBar/ConnectDialog/CosmostationConnectButton.js
+++ b/src/containers/NavBar/ConnectDialog/CosmostationConnectButton.js
@@ -2,7 +2,6 @@ import { Button } from '@material-ui/core';
import React, { useState } from 'react';
import * as PropTypes from 'prop-types';
import { connect } from 'react-redux';
-import { withRouter } from 'react-router';
import {
fetchRewards,
fetchVestingBalance,
@@ -18,6 +17,7 @@ import { encode } from 'js-base64';
import { hideConnectDialog } from '../../../actions/navBar';
import { initializeCosmoStation } from '../../../helper';
import variables from '../../../utils/variables';
+import withRouter from '../../../components/WithRouter';
const CosmostationConnectButton = (props) => {
const [inProgress, setInProgress] = useState(false);
diff --git a/src/containers/NavBar/DisconnectButton.js b/src/containers/NavBar/DisconnectButton.js
index 7b20895..e42b052 100644
--- a/src/containers/NavBar/DisconnectButton.js
+++ b/src/containers/NavBar/DisconnectButton.js
@@ -3,8 +3,8 @@ import { Button } from '@material-ui/core';
import * as PropTypes from 'prop-types';
import { connect } from 'react-redux';
import variables from '../../utils/variables';
-import { withRouter } from 'react-router';
import { disconnectSet } from '../../actions/accounts';
+import withRouter from '../../components/WithRouter';
const DisconnectButton = (props) => {
const handleClick = () => {
@@ -25,10 +25,10 @@ const DisconnectButton = (props) => {
DisconnectButton.propTypes = {
disconnectSet: PropTypes.func.isRequired,
- history: PropTypes.shape({
- push: PropTypes.func.isRequired,
- }).isRequired,
lang: PropTypes.string.isRequired,
+ router: PropTypes.shape({
+ navigate: PropTypes.func.isRequired,
+ }),
};
const stateToProps = (state) => {
diff --git a/src/containers/NavBar/Tabs.js b/src/containers/NavBar/Tabs.js
index 2907ed2..11577a9 100644
--- a/src/containers/NavBar/Tabs.js
+++ b/src/containers/NavBar/Tabs.js
@@ -3,9 +3,9 @@ import * as PropTypes from 'prop-types';
import React, { Component } from 'react';
import { connect } from 'react-redux';
import variables from '../../utils/variables';
-import { withRouter } from 'react-router';
import { hideSideBar } from '../../actions/navBar';
import { hideProposalDialog } from '../../actions/proposals';
+import withRouter from '../../components/WithRouter';
class Tabs extends Component {
constructor (props) {
@@ -17,8 +17,8 @@ class Tabs extends Component {
}
componentDidMount () {
- const route = this.props.location.pathname && this.props.location.pathname.split('/') &&
- this.props.location.pathname.split('/')[1];
+ const route = this.props.router && this.props.router.location && this.props.router.location.pathname &&
+ this.props.router.location.pathname.split('/') && this.props.router.location.pathname.split('/')[1];
if (this.state.value !== route && (route === '' || route === 'stake' || route === 'proposals')) {
this.setState({
@@ -28,8 +28,9 @@ class Tabs extends Component {
}
componentDidUpdate (pp, ps, ss) {
- if (pp.location.pathname !== this.props.location.pathname) {
- const value = this.props.location.pathname.split('/')[1];
+ if (pp.router && pp.router.location && this.props.router && this.props.router.location &&
+ pp.router.location.pathname !== this.props.router.location.pathname) {
+ const value = this.props.router.location.pathname.split('/')[1];
if (value !== this.state.value && (value === '' || value === 'stake' || value === 'proposals')) {
this.setState({
@@ -44,12 +45,12 @@ class Tabs extends Component {
if (this.props.open) {
this.props.hideProposalDialog();
}
- if ((newValue === this.state.value) && (this.props.match &&
- this.props.match.params && !this.props.match.params.proposalID)) {
+ if ((newValue === this.state.value) && (this.props.router &&
+ this.props.router.params && !this.props.router.params.proposalID)) {
return;
}
- this.props.history.push('/' + newValue);
+ this.props.router.navigate('/' + newValue);
this.setState({
value: newValue,
});
@@ -93,18 +94,16 @@ class Tabs extends Component {
Tabs.propTypes = {
handleClose: PropTypes.func.isRequired,
hideProposalDialog: PropTypes.func.isRequired,
- history: PropTypes.shape({
- push: PropTypes.func.isRequired,
- }).isRequired,
lang: PropTypes.string.isRequired,
- location: PropTypes.shape({
- pathname: PropTypes.string.isRequired,
- }).isRequired,
open: PropTypes.bool.isRequired,
- match: PropTypes.shape({
+ router: PropTypes.shape({
+ location: PropTypes.shape({
+ pathname: PropTypes.string.isRequired,
+ }).isRequired,
+ navigate: PropTypes.func.isRequired,
params: PropTypes.shape({
proposalID: PropTypes.string,
- }),
+ }).isRequired,
}),
};
diff --git a/src/containers/NavBar/index.js b/src/containers/NavBar/index.js
index e35391b..2096167 100644
--- a/src/containers/NavBar/index.js
+++ b/src/containers/NavBar/index.js
@@ -23,17 +23,19 @@ import {
showSelectAccountDialog,
} from '../../actions/accounts';
import {
+ fetchAPR,
fetchValidatorImage,
fetchValidatorImageSuccess,
getDelegatedValidatorsDetails,
+ getInActiveValidators,
getValidators,
} from '../../actions/stake';
-import { withRouter } from 'react-router-dom';
import CopyButton from '../../components/CopyButton/TextButton';
import variables from '../../utils/variables';
import { fetchProposalDetails, fetchProposalTally, fetchVoteDetails, getProposals } from '../../actions/proposals';
import { Button } from '@material-ui/core';
import ConnectDialog from './ConnectDialog';
+import withRouter from '../../components/WithRouter';
class NavBar extends Component {
constructor (props) {
@@ -64,7 +66,7 @@ class NavBar extends Component {
if (this.props.proposals && !this.props.proposals.length &&
!this.props.proposalsInProgress && !this.props.stake &&
- this.props.match && this.props.match.params && !this.props.match.params.proposalID) {
+ this.props.router && this.props.router.params && !this.props.router.params.proposalID) {
this.props.getProposals((result) => {
if (result && result.length) {
const array = [];
@@ -89,7 +91,7 @@ class NavBar extends Component {
});
} else if (this.props.proposals && !this.props.proposalsInProgress && !this.props.stake &&
this.props.proposalDetails && Object.keys(this.props.proposalDetails).length === 1 &&
- this.props.match && this.props.match.params && !this.props.match.params.proposalID) {
+ this.props.router && this.props.router.params && !this.props.router.params.proposalID) {
const array = [];
this.props.proposals.map((val) => {
const filter = this.props.proposalDetails && Object.keys(this.props.proposalDetails).length &&
@@ -114,7 +116,7 @@ class NavBar extends Component {
this.handleFetch(this.props.address);
}
- if (!this.props.validatorList.length && !this.props.validatorListInProgress && !this.props.proposalTab) {
+ if (this.props.validatorList && !this.props.validatorList.length && !this.props.validatorListInProgress && !this.props.proposalTab) {
this.props.getValidators((data) => {
if (data && data.length && this.props.validatorImages && this.props.validatorImages.length === 0) {
const array = data.filter((val) => val && val.description && val.description.identity);
@@ -123,31 +125,49 @@ class NavBar extends Component {
});
}
- window.addEventListener('keplr_keystorechange', () => {
- if (localStorage.getItem('of_co_address') || this.props.address !== '') {
- this.handleChain();
- }
- });
+ if (!this.props.actualAPR && !this.props.aprInProgress) {
+ this.props.fetchAPR();
+ }
- window.onload = () => {
- if (window.cosmostation && window.cosmostation.cosmos) {
- const cosmostationEvent = window.cosmostation.cosmos.on('accountChanged', () => {
- if (localStorage.getItem('of_co_address') || this.props.address !== '') {
- this.handleCosmoStation();
- }
- });
+ if (!this.props.inActiveValidatorsList.length && !this.props.inActiveValidatorsInProgress && !this.props.proposalTab) {
+ this.props.getInActiveValidators((data) => {
+ if (data && data.length) {
+ const array = data.filter((val) => val && val.description && val.description.identity);
+ this.getValidatorImage(0, array);
+ }
+ });
+ }
- this.setState({
- cosmostationEvent: cosmostationEvent,
- });
- }
- };
+ if (localStorage.getItem('of_co_wallet') === 'keplr') {
+ window.addEventListener('keplr_keystorechange', () => {
+ if (localStorage.getItem('of_co_address') || this.props.address !== '') {
+ this.handleChain();
+ }
+ });
+ }
+
+ if (localStorage.getItem('of_co_wallet') === 'cosmostation') {
+ window.onload = () => {
+ if (window.cosmostation && window.cosmostation.cosmos) {
+ const cosmostationEvent = window.cosmostation.cosmos.on('accountChanged', () => {
+ if (localStorage.getItem('of_co_address') || this.props.address !== '') {
+ this.handleCosmoStation();
+ }
+ });
+
+ this.setState({
+ cosmostationEvent: cosmostationEvent,
+ });
+ }
+ };
+ }
}
componentDidUpdate (pp, ps, ss) {
- if ((!pp.proposals.length && (pp.proposals !== this.props.proposals) &&
+ if ((pp.proposals && !pp.proposals.length && (pp.proposals !== this.props.proposals) &&
this.props.proposals && this.props.proposals.length) ||
((pp.address !== this.props.address) && (pp.address === '') && (this.props.address !== ''))) {
+ this.props.proposals && this.props.proposals.length &&
this.props.proposals.map((val) => {
const votedOption = this.props.voteDetails && this.props.voteDetails.length && val && val.proposal_id &&
this.props.voteDetails.filter((vote) => vote.proposal_id === val.proposal_id)[0];
@@ -367,9 +387,11 @@ class NavBar extends Component {
}
NavBar.propTypes = {
+ aprInProgress: PropTypes.bool.isRequired,
balanceInProgress: PropTypes.bool.isRequired,
delegatedValidatorListInProgress: PropTypes.bool.isRequired,
delegationsInProgress: PropTypes.bool.isRequired,
+ fetchAPR: PropTypes.func.isRequired,
fetchProposalDetails: PropTypes.func.isRequired,
fetchProposalTally: PropTypes.func.isRequired,
fetchRewards: PropTypes.func.isRequired,
@@ -380,13 +402,13 @@ NavBar.propTypes = {
getBalance: PropTypes.func.isRequired,
getDelegatedValidatorsDetails: PropTypes.func.isRequired,
getDelegations: PropTypes.func.isRequired,
+ getInActiveValidators: PropTypes.func.isRequired,
getProposals: PropTypes.func.isRequired,
getUnBondingDelegations: PropTypes.func.isRequired,
getValidators: PropTypes.func.isRequired,
handleClose: PropTypes.func.isRequired,
- history: PropTypes.shape({
- push: PropTypes.func.isRequired,
- }).isRequired,
+ inActiveValidatorsInProgress: PropTypes.bool.isRequired,
+ inActiveValidatorsList: PropTypes.array.isRequired,
lang: PropTypes.string.isRequired,
proposalDetails: PropTypes.object.isRequired,
proposals: PropTypes.array.isRequired,
@@ -403,6 +425,7 @@ NavBar.propTypes = {
vestingBalanceInProgress: PropTypes.bool.isRequired,
voteDetails: PropTypes.array.isRequired,
voteDetailsInProgress: PropTypes.bool.isRequired,
+ actualAPR: PropTypes.number,
address: PropTypes.string,
balance: PropTypes.array,
delegatedValidatorList: PropTypes.array,
@@ -416,13 +439,14 @@ NavBar.propTypes = {
}),
),
home: PropTypes.bool,
- match: PropTypes.shape({
+ proposalTab: PropTypes.bool,
+ proposalsInProgress: PropTypes.bool,
+ router: PropTypes.shape({
+ navigate: PropTypes.func.isRequired,
params: PropTypes.shape({
proposalID: PropTypes.string,
- }),
+ }).isRequired,
}),
- proposalTab: PropTypes.bool,
- proposalsInProgress: PropTypes.bool,
stake: PropTypes.bool,
unBondingDelegations: PropTypes.arrayOf(
PropTypes.shape({
@@ -438,6 +462,8 @@ NavBar.propTypes = {
const stateToProps = (state) => {
return {
address: state.accounts.address.value,
+ aprInProgress: state.stake.apr.inProgress,
+ actualAPR: state.stake.apr.actualAPR,
balance: state.accounts.balance.result,
balanceInProgress: state.accounts.balance.inProgress,
delegations: state.accounts.delegations.result,
@@ -458,6 +484,8 @@ const stateToProps = (state) => {
vestingBalanceInProgress: state.accounts.vestingBalance.inProgress,
voteDetails: state.proposals.voteDetails.value,
voteDetailsInProgress: state.proposals.voteDetails.inProgress,
+ inActiveValidatorsList: state.stake.inActiveValidators.list,
+ inActiveValidatorsInProgress: state.stake.inActiveValidators.inProgress,
};
};
@@ -471,6 +499,7 @@ const actionToProps = {
showDialog: showSelectAccountDialog,
getUnBondingDelegations,
getValidators,
+ fetchAPR,
fetchRewards,
fetchValidatorImage,
fetchValidatorImageSuccess,
@@ -479,6 +508,7 @@ const actionToProps = {
fetchVoteDetails,
fetchProposalTally,
fetchProposalDetails,
+ getInActiveValidators,
showConnectDialog,
};
diff --git a/src/containers/Proposals/Cards.js b/src/containers/Proposals/Cards.js
index 7c77701..9a2f2c5 100644
--- a/src/containers/Proposals/Cards.js
+++ b/src/containers/Proposals/Cards.js
@@ -9,7 +9,7 @@ import { showProposalDialog } from '../../actions/proposals';
import moment from 'moment';
import { tally } from '../../utils/numberFormats';
import DotsLoading from '../../components/DotsLoading';
-import { withRouter } from 'react-router';
+import withRouter from '../../components/WithRouter';
const Cards = (props) => {
const [page, setPage] = useState(1);
@@ -34,24 +34,44 @@ const Cards = (props) => {
const value = props.tallyDetails && props.tallyDetails[proposal.proposal_id];
const sum = value && value.yes && value.no && value.no_with_veto && value.abstain &&
(parseInt(value.yes) + parseInt(value.no) + parseInt(value.no_with_veto) + parseInt(value.abstain));
+ let val1 = null;
+ if (val === 'yes_count') {
+ val1 = 'yes';
+ } else if (val === 'no_count') {
+ val1 = 'no';
+ } else if (val === 'no_with_veto_count') {
+ val1 = 'no_with_veto';
+ } else if (val === 'abstain_count') {
+ val1 = 'abstain';
+ }
- return (props.tallyDetails && props.tallyDetails[proposal.proposal_id] && props.tallyDetails[proposal.proposal_id][val]
- ? tally(props.tallyDetails[proposal.proposal_id][val], sum) : '0%');
+ return (props.tallyDetails && props.tallyDetails[proposal.proposal_id] && props.tallyDetails[proposal.proposal_id][val1]
+ ? tally(props.tallyDetails[proposal.proposal_id][val1], sum) : '0%');
} else {
const sum = proposal.final_tally_result && proposal.final_tally_result.yes &&
proposal.final_tally_result.no && proposal.final_tally_result.no_with_veto &&
proposal.final_tally_result.abstain &&
(parseInt(proposal.final_tally_result.yes) + parseInt(proposal.final_tally_result.no) +
parseInt(proposal.final_tally_result.no_with_veto) + parseInt(proposal.final_tally_result.abstain));
+ let val1 = null;
+ if (val === 'yes_count') {
+ val1 = 'yes';
+ } else if (val === 'no_count') {
+ val1 = 'no';
+ } else if (val === 'no_with_veto_count') {
+ val1 = 'no_with_veto';
+ } else if (val === 'abstain_count') {
+ val1 = 'abstain';
+ }
return (proposal && proposal.final_tally_result &&
- proposal.final_tally_result[val]
- ? tally(proposal.final_tally_result[val], sum) : '0%');
+ proposal.final_tally_result[val1]
+ ? tally(proposal.final_tally_result[val1], sum) : '0%');
}
};
const handleProposal = (proposal) => {
- props.history.push(`/proposals/${proposal.proposal_id}`);
+ props.router.navigate(`/proposals/${proposal.proposal_id}`);
props.handleShow(proposal);
};
@@ -97,7 +117,7 @@ const Cards = (props) => {
props.handleShow(proposal)}> {
- proposal.content && proposal.content.title
+ proposal.title || (proposal.content && proposal.content.title)
}
{proposal.status === 3 || proposal.status === 'PROPOSAL_STATUS_PASSED'
?
@@ -126,7 +146,7 @@ const Cards = (props) => {
: null}
- {proposal.content && proposal.content.description}
+ {proposal.summary || (proposal.content && proposal.content.description)}
@@ -159,7 +179,7 @@ const Cards = (props) => {
proposal.status === 'PROPOSAL_STATUS_VOTING_PERIOD')
? 'voting_period'
: (proposal.status === 4 ||
- proposal.status === 'PROPOSAL_STATUS_REJECTED')
+ proposal.status === 'PROPOSAL_STATUS_REJECTED' || proposal.status === 'PROPOSAL_STATUS_FAILED')
? 'rejected'
: null)}>
Proposal Status: {
@@ -180,19 +200,19 @@ const Cards = (props) => {
-
YES ({VoteCalculation(proposal, 'yes')})
+
YES ({VoteCalculation(proposal, 'yes_count')})
-
NO ({VoteCalculation(proposal, 'no')})
+
NO ({VoteCalculation(proposal, 'no_count')})
-
NoWithVeto ({VoteCalculation(proposal, 'no_with_veto')})
+
NoWithVeto ({VoteCalculation(proposal, 'no_with_veto_count')})
-
Abstain ({VoteCalculation(proposal, 'abstain')})
+
Abstain ({VoteCalculation(proposal, 'abstain_count')})
@@ -214,9 +234,6 @@ const Cards = (props) => {
Cards.propTypes = {
handleShow: PropTypes.func.isRequired,
- history: PropTypes.shape({
- push: PropTypes.func.isRequired,
- }).isRequired,
proposalDetails: PropTypes.object.isRequired,
proposalDetailsInProgress: PropTypes.bool.isRequired,
tallyDetails: PropTypes.object.isRequired,
@@ -225,6 +242,9 @@ Cards.propTypes = {
home: PropTypes.bool,
proposals: PropTypes.array,
proposalsInProgress: PropTypes.bool,
+ router: PropTypes.shape({
+ navigate: PropTypes.func.isRequired,
+ }),
};
const stateToProps = (state) => {
diff --git a/src/containers/Proposals/ProposalDialog/index.js b/src/containers/Proposals/ProposalDialog/index.js
index 307dc8f..68d27f9 100644
--- a/src/containers/Proposals/ProposalDialog/index.js
+++ b/src/containers/Proposals/ProposalDialog/index.js
@@ -16,12 +16,12 @@ import Voting from './Voting';
import moment from 'moment';
import ClassNames from 'classnames';
import { tally } from '../../../utils/numberFormats';
-import { withRouter } from 'react-router-dom';
import NavBar from '../../NavBar';
import variables from '../../../utils/variables';
import UnSuccessDialog from '../../Stake/DelegateDialog/UnSuccessDialog';
import PendingDialog from '../../Stake/DelegateDialog/PendingDialog';
import SuccessDialog from '../../Stake/DelegateDialog/SuccessDialog';
+import withRouter from '../../../components/WithRouter';
class ProposalDialog extends Component {
constructor (props) {
@@ -44,11 +44,11 @@ class ProposalDialog extends Component {
this.props.fetchVoteDetails(this.props.proposal.proposal_id, this.props.address);
}
- if (this.props.match && this.props.match.params && this.props.match.params.proposalID) {
+ if (this.props.router && this.props.router.params && this.props.router.params.proposalID) {
if (this.props.proposal && !this.props.proposal.proposal_id) {
this.props.getProposals((result) => {
if (result && result.length) {
- const proposal = result.find((val) => val.proposal_id === this.props.match.params.proposalID);
+ const proposal = result.find((val) => val.proposal_id === this.props.router.params.proposalID);
this.props.showProposalDialog(proposal);
if (proposal && (proposal.status === 2 || proposal.status === 'PROPOSAL_STATUS_VOTING_PERIOD')) {
this.props.fetchProposalTally(proposal.proposal_id);
@@ -57,8 +57,8 @@ class ProposalDialog extends Component {
});
}
- if (this.props.proposalDetails && !this.props.proposalDetails[this.props.match.params.proposalID]) {
- this.props.fetchProposalDetails(this.props.match.params.proposalID);
+ if (this.props.proposalDetails && !this.props.proposalDetails[this.props.router.params.proposalID]) {
+ this.props.fetchProposalDetails(this.props.router.params.proposalID);
}
}
}
@@ -76,24 +76,44 @@ class ProposalDialog extends Component {
const value = this.props.tallyDetails && this.props.tallyDetails[proposal.proposal_id];
const sum = value && value.yes && value.no && value.no_with_veto && value.abstain &&
(parseInt(value.yes) + parseInt(value.no) + parseInt(value.no_with_veto) + parseInt(value.abstain));
+ let val1 = null;
+ if (val === 'yes_count') {
+ val1 = 'yes';
+ } else if (val === 'no_count') {
+ val1 = 'no';
+ } else if (val === 'no_with_veto_count') {
+ val1 = 'no_with_veto';
+ } else if (val === 'abstain_count') {
+ val1 = 'abstain';
+ }
- return (this.props.tallyDetails && this.props.tallyDetails[proposal.proposal_id] && this.props.tallyDetails[proposal.proposal_id][val]
- ? tally(this.props.tallyDetails[proposal.proposal_id][val], sum) : '0%');
+ return (this.props.tallyDetails && this.props.tallyDetails[proposal.proposal_id] && this.props.tallyDetails[proposal.proposal_id][val1]
+ ? tally(this.props.tallyDetails[proposal.proposal_id][val1], sum) : '0%');
} else {
const sum = proposal && proposal.final_tally_result && proposal.final_tally_result.yes &&
proposal.final_tally_result.no && proposal.final_tally_result.no_with_veto &&
proposal.final_tally_result.abstain &&
(parseInt(proposal.final_tally_result.yes) + parseInt(proposal.final_tally_result.no) +
parseInt(proposal.final_tally_result.no_with_veto) + parseInt(proposal.final_tally_result.abstain));
+ let val1 = null;
+ if (val === 'yes_count') {
+ val1 = 'yes';
+ } else if (val === 'no_count') {
+ val1 = 'no';
+ } else if (val === 'no_with_veto_count') {
+ val1 = 'no_with_veto';
+ } else if (val === 'abstain_count') {
+ val1 = 'abstain';
+ }
return (proposal && proposal.final_tally_result &&
- proposal.final_tally_result[val]
- ? tally(proposal.final_tally_result[val], sum) : '0%');
+ proposal.final_tally_result[val1]
+ ? tally(proposal.final_tally_result[val1], sum) : '0%');
}
}
handleClose () {
- this.props.history.push('/proposals');
+ this.props.router.navigate('/proposals');
this.props.handleClose();
}
@@ -101,6 +121,9 @@ class ProposalDialog extends Component {
let votedOption = this.props.voteDetails && this.props.voteDetails.length &&
this.props.proposal && this.props.proposal.proposal_id &&
this.props.voteDetails.filter((vote) => vote && (vote.proposal_id === this.props.proposal.proposal_id))[0];
+ if (votedOption && votedOption.options && votedOption.options.length && votedOption.options[0]) {
+ votedOption = votedOption.options[0];
+ }
let proposer = this.props.proposal && this.props.proposal.proposer;
this.props.proposalDetails && Object.keys(this.props.proposalDetails).length &&
@@ -120,10 +143,6 @@ class ProposalDialog extends Component {
return null;
});
- if (votedOption && votedOption.options && votedOption.options.length) {
- votedOption = votedOption.options[0];
- }
-
return (
@@ -146,7 +165,7 @@ class ProposalDialog extends Component {
(this.props.proposal.status === 2 || this.props.proposal.status === 'PROPOSAL_STATUS_VOTING_PERIOD')
? 'voting_period'
: this.props.proposal && (this.props.proposal.status === 4 ||
- this.props.proposal.status === 'PROPOSAL_STATUS_REJECTED')
+ this.props.proposal.status === 'PROPOSAL_STATUS_REJECTED' || this.props.proposal.status === 'PROPOSAL_STATUS_FAILED')
? 'rejected'
: null)}> Proposal
Status: {this.props.proposal && this.props.proposal.status
@@ -208,19 +227,19 @@ class ProposalDialog extends Component {
this.props.proposal.status === 'PROPOSAL_STATUS_VOTING_PERIOD') ? 'vote_in_progress' : '')}>
-
YES ({this.VoteCalculation('yes')})
+
YES ({this.VoteCalculation('yes_count')})
-
NO ({this.VoteCalculation('no')})
+
NO ({this.VoteCalculation('no_count')})
-
NoWithVeto ({this.VoteCalculation('no_with_veto')})
+
NoWithVeto ({this.VoteCalculation('no_with_veto_count')})
-
Abstain ({this.VoteCalculation('abstain')})
+
Abstain ({this.VoteCalculation('abstain_count')})
@@ -274,9 +293,6 @@ ProposalDialog.propTypes = {
fetchVoteDetails: PropTypes.func.isRequired,
getProposals: PropTypes.func.isRequired,
handleClose: PropTypes.func.isRequired,
- history: PropTypes.shape({
- push: PropTypes.func.isRequired,
- }).isRequired,
lang: PropTypes.string.isRequired,
proposalDetails: PropTypes.object.isRequired,
showProposalDialog: PropTypes.func.isRequired,
@@ -284,16 +300,17 @@ ProposalDialog.propTypes = {
voteDetails: PropTypes.array.isRequired,
voteDetailsInProgress: PropTypes.bool.isRequired,
address: PropTypes.string,
- match: PropTypes.shape({
+ proposal: PropTypes.object,
+ proposalsInProgress: PropTypes.bool,
+ router: PropTypes.shape({
+ navigate: PropTypes.func.isRequired,
params: PropTypes.shape({
proposalID: PropTypes.string,
- }),
+ }).isRequired,
}),
- proposal: PropTypes.object,
- proposalsInProgress: PropTypes.bool,
votes: PropTypes.arrayOf(
PropTypes.shape({
- proposal_id: PropTypes.string.isRequired,
+ id: PropTypes.string.isRequired,
voter: PropTypes.string.isRequired,
option: PropTypes.number,
}),
diff --git a/src/containers/Proposals/index.js b/src/containers/Proposals/index.js
index e353a31..0edf483 100644
--- a/src/containers/Proposals/index.js
+++ b/src/containers/Proposals/index.js
@@ -2,7 +2,6 @@ import React, { useState } from 'react';
import NavBar from '../NavBar';
import variables from '../../utils/variables';
import * as PropTypes from 'prop-types';
-import { withRouter } from 'react-router-dom';
import { connect } from 'react-redux';
import './index.css';
import Cards from './Cards';
@@ -10,6 +9,7 @@ import { fetchProposalTally, fetchVoteDetails, getProposals } from '../../action
import UnSuccessDialog from '../Stake/DelegateDialog/UnSuccessDialog';
import PendingDialog from '../Stake/DelegateDialog/PendingDialog';
import SuccessDialog from '../Stake/DelegateDialog/SuccessDialog';
+import withRouter from '../../components/WithRouter';
const Proposals = (props) => {
const [active, setActive] = useState(1);
@@ -50,6 +50,7 @@ const Proposals = (props) => {
{variables[props.lang].closed}
+ Voting Period: 8 Days
{props.proposalsInProgress || props.voteDetailsInProgress
? Loading...
@@ -68,15 +69,15 @@ Proposals.propTypes = {
fetchProposalTally: PropTypes.func.isRequired,
fetchVoteDetails: PropTypes.func.isRequired,
getProposals: PropTypes.func.isRequired,
- history: PropTypes.shape({
- push: PropTypes.func.isRequired,
- }).isRequired,
lang: PropTypes.string.isRequired,
proposals: PropTypes.array.isRequired,
voteDetails: PropTypes.array.isRequired,
voteDetailsInProgress: PropTypes.bool.isRequired,
address: PropTypes.string,
proposalsInProgress: PropTypes.bool,
+ router: PropTypes.shape({
+ navigate: PropTypes.func.isRequired,
+ }),
};
const stateToProps = (state) => {
diff --git a/src/containers/Snackbar.js b/src/containers/Snackbar.js
index 154f761..810f598 100644
--- a/src/containers/Snackbar.js
+++ b/src/containers/Snackbar.js
@@ -3,7 +3,7 @@ import { connect } from 'react-redux';
import * as PropTypes from 'prop-types';
import { hideSnackbar } from '../actions/snackbar';
import Snackbar from '../components/Snackbar';
-import { withRouter } from 'react-router';
+import withRouter from '../components/WithRouter';
class SnackbarMessage extends Component {
componentDidUpdate (pp, ps, ss) {
@@ -15,7 +15,7 @@ class SnackbarMessage extends Component {
this.props.onClose();
localStorage.removeItem('of_co_address');
- this.props.history.push('/');
+ this.props.router.navigate('/');
break;
default:
@@ -35,12 +35,12 @@ class SnackbarMessage extends Component {
}
SnackbarMessage.propTypes = {
- history: PropTypes.shape({
- push: PropTypes.func.isRequired,
- }).isRequired,
message: PropTypes.string.isRequired,
open: PropTypes.bool.isRequired,
onClose: PropTypes.func.isRequired,
+ router: PropTypes.shape({
+ navigate: PropTypes.func.isRequired,
+ }),
};
const stateToProps = (state) => {
diff --git a/src/containers/Stake/DelegateDialog/MultiValidatorSelectField.js b/src/containers/Stake/DelegateDialog/MultiValidatorSelectField.js
new file mode 100644
index 0000000..b65cb65
--- /dev/null
+++ b/src/containers/Stake/DelegateDialog/MultiValidatorSelectField.js
@@ -0,0 +1,135 @@
+import React from 'react';
+import * as PropTypes from 'prop-types';
+import { connect } from 'react-redux';
+import { setValidator, selectMultiValidators } from '../../../actions/stake';
+import { MenuItem, Checkbox, FormControl, Select, OutlinedInput, Divider, ListItemIcon } from '@material-ui/core';
+
+const colors = ['#0023DA', '#C9387E', '#EC2C00', '#80E3F2',
+ '#E86FC5', '#1F3278', '#FFE761', '#7041B9'];
+
+const MultiValidatorSelectField = (props) => {
+ const validatorList = [...props.validatorList];
+ const handleChange = (event) => {
+ const value = event.target.value;
+
+ if (value[value.length - 1] === 'all') {
+ props.selectMultiValidators(props.selectedMultiValidatorArray.length === validatorList.length ? [] : (validatorList.map((item) => item.operator_address)));
+ } else {
+ props.selectMultiValidators(typeof value === 'string' ? value.split(',') : value);
+ }
+
+ if (props.value === value) {
+ return;
+ }
+ props.onChange(value);
+ };
+
+ const isAllSelected = validatorList.length > 0 && props.selectedMultiValidatorArray.length === validatorList.length;
+
+ return (
+ <>
+
+
+
+ >
+ );
+};
+
+MultiValidatorSelectField.propTypes = {
+ selectMultiValidators: PropTypes.func.isRequired,
+ selectedMultiValidatorArray: PropTypes.array.isRequired,
+ validatorImages: PropTypes.array.isRequired,
+ value: PropTypes.string.isRequired,
+ onChange: PropTypes.func.isRequired,
+ validatorList: PropTypes.arrayOf(
+ PropTypes.shape({
+ operator_address: PropTypes.string,
+ status: PropTypes.number,
+ description: PropTypes.shape({
+ moniker: PropTypes.string,
+ }),
+ }),
+ ),
+};
+
+const stateToProps = (state) => {
+ return {
+ value: state.stake.validator.value,
+ validatorList: state.stake.validators.list,
+ validatorImages: state.stake.validators.images,
+ selectedMultiValidatorArray: state.stake.selectMultiValidators.list,
+ };
+};
+
+const actionToProps = {
+ onChange: setValidator,
+ selectMultiValidators,
+};
+
+export default connect(stateToProps, actionToProps)(MultiValidatorSelectField);
diff --git a/src/containers/Stake/DelegateDialog/SuccessDialog.js b/src/containers/Stake/DelegateDialog/SuccessDialog.js
index dfadbec..0c74561 100644
--- a/src/containers/Stake/DelegateDialog/SuccessDialog.js
+++ b/src/containers/Stake/DelegateDialog/SuccessDialog.js
@@ -1,25 +1,49 @@
import React from 'react';
import * as PropTypes from 'prop-types';
import { connect } from 'react-redux';
-import { Button, Dialog, DialogActions, DialogContent } from '@material-ui/core';
+import { Button, Dialog, DialogActions, DialogContent, ListItem, Tooltip, withStyles } from '@material-ui/core';
import './index.css';
import variables from '../../../utils/variables';
import { hideDelegateSuccessDialog } from '../../../actions/stake';
import success from '../../../assets/stake/success.svg';
import { config } from '../../../config';
-import { withRouter } from 'react-router-dom';
+import withRouter from '../../../components/WithRouter';
+
+const colors = ['#0023DA', '#C9387E', '#EC2C00', '#80E3F2',
+ '#E86FC5', '#1F3278', '#FFE761', '#7041B9'];
+
+const CustomTooltip = withStyles(() => ({
+ tooltip: {
+ maxWidth: '650px',
+ maxHeight: '180px',
+ background: '#1E1E1E',
+ color: '#ffffff',
+ overflow: 'auto',
+ scrollbarWidth: 'thin',
+ '&::-webkit-scrollbar': {
+ width: '4px',
+ },
+ '&::-webkit-scrollbar-track': {
+ backgroundColor: '#1E1E1E',
+ },
+ '&::-webkit-scrollbar-thumb': {
+ backgroundColor: '#ffffff',
+ borderRadius: '1px',
+ },
+ },
+}))(Tooltip);
const SuccessDialog = (props) => {
const handleRedirect = () => {
if (config.EXPLORER_URL) {
- const link = `${config.EXPLORER_URL}/transactions/${props.hash}`;
+ const link = `${config.EXPLORER_URL}/txs/${props.hash}`;
window.open(link, '_blank');
}
};
const handleClose = () => {
- if (props.match && props.match.params && props.match.params.proposalID) {
- props.history.push('/proposals');
+ if (props.router && props.router.params && props.router.params.proposalID) {
+ props.router.navigate('/proposals');
}
props.handleClose();
@@ -29,6 +53,7 @@ const SuccessDialog = (props) => {
props.validatorList.find((val) => val.operator_address === props.validator);
const toValidatorDetails = props.validatorList && props.validatorList.length &&
props.validatorList.find((val) => val.operator_address === props.toValidator);
+ const delegatedList = props.validatorList.filter((item) => props.selectedMultiValidatorArray.includes(item.operator_address));
return (