Skip to content

Commit

Permalink
metamask integration. (#102)
Browse files Browse the repository at this point in the history
  • Loading branch information
SrikanthSoparla committed Jan 12, 2024
1 parent bfdd269 commit 16f067c
Show file tree
Hide file tree
Showing 12 changed files with 344 additions and 25 deletions.
2 changes: 1 addition & 1 deletion src/actions/proposals.js
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ export const fetchProposalTally = (id) => (dispatch) => {
},
})
.then((res) => {
dispatch(fetchProposalTallySuccess(res.data && res.data.result, id));
dispatch(fetchProposalTallySuccess(res.data && res.data.tally, id));
})
.catch((error) => {
dispatch(fetchProposalTallyError(
Expand Down
Binary file added src/assets/MetaMask.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 11 additions & 1 deletion src/containers/Home/ClaimDialog/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
import { connect } from 'react-redux';
import '../../Stake/DelegateDialog/index.css';
import ValidatorsSelectField from './ValidatorsSelectField';
import { cosmoStationSign, signTxAndBroadcast } from '../../../helper';
import { cosmoStationSign, metaMaskSign, signTxAndBroadcast } from '../../../helper';
import { showMessage } from '../../../actions/snackbar';
import { fetchRewards, fetchVestingBalance, getBalance } from '../../../actions/accounts';
import { config } from '../../../config';
Expand Down Expand Up @@ -61,6 +61,11 @@ const ClaimDialog = (props) => {
return;
}

if (localStorage.getItem('of_co_wallet') === 'metamask') {
metaMaskSign(updatedTx, props.address, handleFetch);
return;
}

signTxAndBroadcast(updatedTx, props.address, handleFetch);
};

Expand Down Expand Up @@ -112,6 +117,11 @@ const ClaimDialog = (props) => {
return;
}

if (localStorage.getItem('of_co_wallet') === 'metamask') {
metaMaskSign(updatedTx, props.address, handleFetch);
return;
}

signTxAndBroadcast(updatedTx, props.address, handleFetch);
};

Expand Down
102 changes: 102 additions & 0 deletions src/containers/NavBar/ConnectDialog/MetaMaskConnectButton.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import React, { useState } from 'react';
import { Button } from '@material-ui/core';
import * as PropTypes from 'prop-types';
import { initializeMetaMask } from '../../../helper';
import {
fetchRewards,
fetchVestingBalance,
getBalance,
getDelegations,
getUnBondingDelegations,
setAccountAddress,
showSelectAccountDialog,
} from '../../../actions/accounts';
import { connect } from 'react-redux';
import { showMessage } from '../../../actions/snackbar';
import { encode } from 'js-base64';
import { getDelegatedValidatorsDetails } from '../../../actions/stake';
import MetaMaskIcon from '../../../assets/MetaMask.png';
import { hideConnectDialog } from '../../../actions/navBar';
import variables from '../../../utils/variables';

const MetaMaskConnectButton = (props) => {
const [inProgress, setInProgress] = useState(false);

const initKeplr = () => {
setInProgress(true);
initializeMetaMask((error, addressList) => {
setInProgress(false);
if (error) {
localStorage.removeItem('of_co_address');
props.showMessage(error);

return;
}

props.setAccountAddress(addressList && addressList.address && addressList.address.address);
props.hideConnectDialog();
if (!props.proposalTab && !props.stake) {
props.getUnBondingDelegations(addressList && addressList.address && addressList.address.address);
props.fetchRewards(addressList && addressList.address && addressList.address.address);
}
if (!props.proposalTab) {
props.getDelegations(addressList && addressList.address && addressList.address.address);
}
props.getBalance(addressList && addressList.address && addressList.address.address);
props.fetchVestingBalance(addressList && addressList.address && addressList.address.address);
if (!props.proposalTab) {
props.getDelegatedValidatorsDetails(addressList && addressList.address && addressList.address.address);
}
localStorage.setItem('of_co_address', encode(addressList && addressList.address && addressList.address.address));
localStorage.setItem('of_co_wallet', 'metamask');
});
};

return (
<Button
className="disconnect_button"
disabled={inProgress}
variant="contained"
onClick={initKeplr}>
<img alt="metamask" src={MetaMaskIcon}/>
{inProgress ? variables[props.lang].connecting + '...' : variables[props.lang].metamask}
</Button>
);
};

MetaMaskConnectButton.propTypes = {
fetchRewards: PropTypes.func.isRequired,
fetchVestingBalance: PropTypes.func.isRequired,
getBalance: PropTypes.func.isRequired,
getDelegatedValidatorsDetails: PropTypes.func.isRequired,
getDelegations: PropTypes.func.isRequired,
getUnBondingDelegations: PropTypes.func.isRequired,
hideConnectDialog: PropTypes.func.isRequired,
lang: PropTypes.string.isRequired,
setAccountAddress: PropTypes.func.isRequired,
showDialog: PropTypes.func.isRequired,
showMessage: PropTypes.func.isRequired,
proposalTab: PropTypes.bool,
stake: PropTypes.bool,
};

const stateToProps = (state) => {
return {
lang: state.language,
};
};

const actionsToProps = {
showMessage,
setAccountAddress,
showDialog: showSelectAccountDialog,
getDelegations,
getDelegatedValidatorsDetails,
fetchVestingBalance,
hideConnectDialog,
getBalance,
getUnBondingDelegations,
fetchRewards,
};

export default connect(stateToProps, actionsToProps)(MetaMaskConnectButton);
11 changes: 11 additions & 0 deletions src/containers/NavBar/ConnectDialog/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import insync from '../../../assets/insync.png';
// import poweredBy from '../../../assets/powered_by.jpeg';
import './index.css';
import { config } from '../../../config';
import MetaMaskConnectButton from './MetaMaskConnectButton';

const LightTooltip = withStyles((theme) => ({
tooltip: {
Expand All @@ -36,6 +37,16 @@ const ConnectDialog = (props) => {
supported wallets
</h2>
<div className="connect_wallets">
<div className="button_div">
<MetaMaskConnectButton proposalTab={props.proposalTab} stake={props.stake}/>
<LightTooltip title="Download the MetaMask Extension">
<IconButton
className="download_button"
onClick={() => window.open('https://chromewebstore.google.com/detail/metamask/nkbihfbeogaeaoehlefnkodbefgpgknn')}>
<GetAppRoundedIcon/>
</IconButton>
</LightTooltip>
</div>
<div className="button_div">
<ConnectButton proposalTab={props.proposalTab} stake={props.stake}/>
<LightTooltip title="Download the Keplr Extension">
Expand Down
56 changes: 45 additions & 11 deletions src/containers/NavBar/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { connect } from 'react-redux';
import ClassNames from 'classnames';
import { hideSideBar, showConnectDialog } from '../../actions/navBar';
import Icon from '../../components/Icon';
import { initializeChain, initializeCosmoStation } from '../../helper';
import { initializeChain, initializeCosmoStation, initializeMetaMask } from '../../helper';
import { decode, encode } from 'js-base64';
import { config } from '../../config';
import { showMessage } from '../../actions/snackbar';
Expand Down Expand Up @@ -49,13 +49,18 @@ class NavBar extends Component {
this.getValidatorImage = this.getValidatorImage.bind(this);
this.getProposalDetails = this.getProposalDetails.bind(this);
this.handleCosmoStation = this.handleCosmoStation.bind(this);
this.handleMetaMask = this.handleMetaMask.bind(this);
}

componentDidMount () {
if (localStorage.getItem('of_co_address') && (localStorage.getItem('of_co_wallet') === 'cosmostation')) {
setTimeout(() => {
this.handleCosmoStation(true);
}, 600);
} else if (localStorage.getItem('of_co_address') && (localStorage.getItem('of_co_wallet') === 'metamask')) {
setTimeout(() => {
this.handleMetaMask(true);
}, 600);
} else if (localStorage.getItem('of_co_address')) {
setTimeout(() => {
this.initKeplr();
Expand All @@ -70,7 +75,7 @@ class NavBar extends Component {
const array = [];
result.map((val) => {
const filter = this.props.proposalDetails && Object.keys(this.props.proposalDetails).length &&
Object.keys(this.props.proposalDetails).find((key) => key === val.proposal_id);
Object.keys(this.props.proposalDetails).find((key) => key === val.id);
if (!filter) {
if (this.props.home && (val.status !== 'PROPOSAL_STATUS_VOTING_PERIOD')) {
return null;
Expand All @@ -79,7 +84,7 @@ class NavBar extends Component {
array.push(val.proposal_id);
}
if (val.status === 2 || val.status === 'PROPOSAL_STATUS_VOTING_PERIOD') {
this.props.fetchProposalTally(val.proposal_id);
this.props.fetchProposalTally(val.id);
}

return null;
Expand All @@ -93,7 +98,7 @@ class NavBar extends Component {
const array = [];
this.props.proposals.map((val) => {
const filter = this.props.proposalDetails && Object.keys(this.props.proposalDetails).length &&
Object.keys(this.props.proposalDetails).find((key) => key === val.proposal_id);
Object.keys(this.props.proposalDetails).find((key) => key === val.id);
if (!filter) {
if (this.props.home && (val.status !== 'PROPOSAL_STATUS_VOTING_PERIOD')) {
return null;
Expand All @@ -102,7 +107,7 @@ class NavBar extends Component {
array.push(val.proposal_id);
}
if (val.status === 2 || val.status === 'PROPOSAL_STATUS_VOTING_PERIOD') {
this.props.fetchProposalTally(val.proposal_id);
this.props.fetchProposalTally(val.id);
}

return null;
Expand Down Expand Up @@ -142,19 +147,30 @@ class NavBar extends Component {
});
}
};

if (window.ethereum) {
window.ethereum && window.ethereum.on('accountsChanged', (accounts) => {
if (accounts.length === 0) {
showMessage('Please connect to MetaMask.');
return;
}

this.handleMetaMask();
});
}
}

componentDidUpdate (pp, ps, ss) {
if ((!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.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];
const votedOption = this.props.voteDetails && this.props.voteDetails.length && val && val.id &&
this.props.voteDetails.filter((vote) => vote && vote.id === val.id)[0];

if ((val.status === 2 || val.status === 'PROPOSAL_STATUS_VOTING_PERIOD') &&
!votedOption && this.props.address) {
this.props.fetchVoteDetails(val.proposal_id, this.props.address);
this.props.fetchVoteDetails(val.id, this.props.address);
}

return null;
Expand All @@ -168,7 +184,7 @@ class NavBar extends Component {
const array = [];
result.map((val) => {
const filter = this.props.proposalDetails && Object.keys(this.props.proposalDetails).length &&
Object.keys(this.props.proposalDetails).find((key) => key === val.proposal_id);
Object.keys(this.props.proposalDetails).find((key) => key === val.id);
if (!filter) {
if (this.props.home && (val.status !== 'PROPOSAL_STATUS_VOTING_PERIOD')) {
return null;
Expand All @@ -177,8 +193,8 @@ class NavBar extends Component {
array.push(val.proposal_id);
}
if (val.status === 2 || val.status === 'PROPOSAL_STATUS_VOTING_PERIOD') {
this.props.fetchProposalTally(val.proposal_id);
this.props.fetchVoteDetails(val.proposal_id, this.props.address);
this.props.fetchProposalTally(val.id);
this.props.fetchVoteDetails(val.id, this.props.address);
}

return null;
Expand Down Expand Up @@ -324,6 +340,24 @@ class NavBar extends Component {
});
}

handleMetaMask (fetch) {
initializeMetaMask((error, account) => {
if (error) {
this.props.showMessage(error);
localStorage.removeItem('of_co_address');

return;
}

this.props.setAccountAddress(account && account.address && account.address.address);
if (fetch) {
this.handleFetch(account && account.address && account.address.address);
}
localStorage.setItem('of_co_address', encode(account && account.address && account.address.address));
localStorage.setItem('of_co_wallet', 'metamask');
});
}

render () {
return (
<div className={ClassNames('nav_bar padding', localStorage.getItem('of_co_address') || this.props.address
Expand Down
22 changes: 16 additions & 6 deletions src/containers/Proposals/Cards.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,21 @@ const Cards = (props) => {
const VoteCalculation = (proposal, val) => {
if (proposal.status === 2 || proposal.status === 'PROPOSAL_STATUS_VOTING_PERIOD') {
const value = props.tallyDetails && props.tallyDetails[proposal.id];
const sum = value && value.yes_count && value.no_count && value.no_with_veto_count && value.abstain_count &&
(parseInt(value.yes_count) + parseInt(value.no_count) + parseInt(value.no_with_veto_count) + parseInt(value.abstain_count));

return (props.tallyDetails && props.tallyDetails[proposal.id] && props.tallyDetails[proposal.id][val]
? tally(props.tallyDetails[proposal.id][val], sum) : '0%');
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.id] && props.tallyDetails[proposal.id][val1]
? tally(props.tallyDetails[proposal.id][val1], sum) : '0%');
} else {
const sum = proposal.final_tally_result && proposal.final_tally_result.yes_count &&
proposal.final_tally_result.no_count && proposal.final_tally_result.no_with_veto_count &&
Expand All @@ -63,7 +73,7 @@ const Cards = (props) => {
if (index < (page * rowsPerPage) && index >= (page - 1) * rowsPerPage) {
const votedOption = props.voteDetails && props.voteDetails.length &&
proposal && proposal.id &&
props.voteDetails.filter((vote) => vote.id === proposal.id)[0];
props.voteDetails.filter((vote) => vote && vote.id === proposal.id)[0];
let proposer = proposal.proposer;
props.proposalDetails && Object.keys(props.proposalDetails).length &&
Object.keys(props.proposalDetails).filter((key) => {
Expand Down
7 changes: 6 additions & 1 deletion src/containers/Proposals/ProposalDialog/Voting.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { fetchProposalTally, fetchVoteDetails, hideProposalDialog } from '../../
import { connect } from 'react-redux';
import { Button, FormControlLabel, Radio, RadioGroup } from '@material-ui/core';
import CircularProgress from '../../../components/CircularProgress';
import { cosmoStationSign, signTxAndBroadcast } from '../../../helper';
import { cosmoStationSign, metaMaskSign, signTxAndBroadcast } from '../../../helper';
import { config } from '../../../config';
import variables from '../../../utils/variables';
import { showMessage } from '../../../actions/snackbar';
Expand Down Expand Up @@ -68,6 +68,11 @@ const Voting = (props) => {
return;
}

if (localStorage.getItem('of_co_wallet') === 'metamask') {
metaMaskSign(tx, props.address, handleFetch);
return;
}

signTxAndBroadcast(tx, props.address, handleFetch);
};

Expand Down
8 changes: 4 additions & 4 deletions src/containers/Proposals/ProposalDialog/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class ProposalDialog extends Component {

componentDidMount () {
const votedOption = this.props.voteDetails && this.props.voteDetails.length && this.props.proposal && this.props.proposal.id &&
this.props.voteDetails.filter((vote) => vote.id === this.props.proposal.id)[0];
this.props.voteDetails.filter((vote) => vote && vote.id === this.props.proposal.id)[0];

if (!votedOption && this.props.proposal && this.props.proposal.id && this.props.address) {
this.props.fetchVoteDetails(this.props.proposal.id, this.props.address);
Expand Down Expand Up @@ -74,8 +74,8 @@ class ProposalDialog extends Component {

if (proposal && (proposal.status === 2 || proposal.status === 'PROPOSAL_STATUS_VOTING_PERIOD')) {
const value = this.props.tallyDetails && this.props.tallyDetails[proposal.id];
const sum = value && value.yes_count && value.no_count && value.no_with_veto_count && value.abstain_count &&
(parseInt(value.yes_count) + parseInt(value.no_count) + parseInt(value.no_with_veto_count) + parseInt(value.abstain_count));
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));

return (this.props.tallyDetails && this.props.tallyDetails[proposal.id] && this.props.tallyDetails[proposal.id][val]
? tally(this.props.tallyDetails[proposal.id][val], sum) : '0%');
Expand All @@ -100,7 +100,7 @@ class ProposalDialog extends Component {
render () {
let votedOption = this.props.voteDetails && this.props.voteDetails.length &&
this.props.proposal && this.props.proposal.id &&
this.props.voteDetails.filter((vote) => vote.id === this.props.proposal.id)[0];
this.props.voteDetails.filter((vote) => vote && vote.id === this.props.proposal.id)[0];
let proposer = this.props.proposal && this.props.proposal.proposer;

this.props.proposalDetails && Object.keys(this.props.proposalDetails).length &&
Expand Down
Loading

0 comments on commit 16f067c

Please sign in to comment.