Working Refunds (#32)
* Add and use placeholder component. * Allow debugging from truffle * Implement refunding * Fix tsc * Double transaction for first refund.
This commit is contained in:
parent
ab66cf6ea4
commit
df1160acf5
|
@ -0,0 +1,17 @@
|
||||||
|
import React from 'react';
|
||||||
|
import * as Styled from './styled';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
title?: React.ReactNode;
|
||||||
|
subtitle?: React.ReactNode;
|
||||||
|
style?: React.CSSProperties;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Placeholder: React.SFC<Props> = ({ style = {}, title, subtitle }) => (
|
||||||
|
<Styled.Container style={style}>
|
||||||
|
{title && <Styled.Title>{title}</Styled.Title>}
|
||||||
|
{subtitle && <Styled.Subtitle>{subtitle}</Styled.Subtitle>}
|
||||||
|
</Styled.Container>
|
||||||
|
);
|
||||||
|
|
||||||
|
export default Placeholder;
|
|
@ -0,0 +1,26 @@
|
||||||
|
import styled from 'styled-components';
|
||||||
|
|
||||||
|
export const Container = styled.div`
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
border: 2px dashed #d9d9d9;
|
||||||
|
padding: 3rem;
|
||||||
|
border-radius: 8px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const Title = styled.h3`
|
||||||
|
margin-bottom: 0;
|
||||||
|
color: rgba(0, 0, 0, 0.6);
|
||||||
|
font-size: 1.6rem;
|
||||||
|
|
||||||
|
& + div {
|
||||||
|
margin-top: 1rem;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const Subtitle = styled.div`
|
||||||
|
color: rgba(0, 0, 0, 0.4);
|
||||||
|
font-size: 1rem;
|
||||||
|
`;
|
|
@ -187,30 +187,15 @@ class Milestones extends React.Component<Props> {
|
||||||
<>
|
<>
|
||||||
<div style={{ display: 'flex', alignItems: 'center' }}>
|
<div style={{ display: 'flex', alignItems: 'center' }}>
|
||||||
{showVoteProgress && (
|
{showVoteProgress && (
|
||||||
<div
|
<Styled.ProgressContainer>
|
||||||
style={{
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'column',
|
|
||||||
margin: '0 2rem 0.5rem 0',
|
|
||||||
textAlign: 'center',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Progress
|
<Progress
|
||||||
type="dashboard"
|
type="dashboard"
|
||||||
percent={activeVoteMilestone.percentAgainstPayout}
|
percent={activeVoteMilestone.percentAgainstPayout}
|
||||||
format={p => `${p}%`}
|
format={p => `${p}%`}
|
||||||
status="exception"
|
status="exception"
|
||||||
/>
|
/>
|
||||||
<div
|
<Styled.ProgressText>voted against payout</Styled.ProgressText>
|
||||||
style={{
|
</Styled.ProgressContainer>
|
||||||
whiteSpace: 'nowrap',
|
|
||||||
opacity: 0.6,
|
|
||||||
fontSize: '0.75rem',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
voted against payout
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
<div>
|
<div>
|
||||||
{content}
|
{content}
|
||||||
|
|
|
@ -1,56 +1,182 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Spin, Progress, Button } from 'antd';
|
import { connect } from 'react-redux';
|
||||||
|
import { Spin, Progress, Button, Alert } from 'antd';
|
||||||
import { ProposalWithCrowdFund } from 'modules/proposals/reducers';
|
import { ProposalWithCrowdFund } from 'modules/proposals/reducers';
|
||||||
import Web3Container, { Web3RenderProps } from 'lib/Web3Container';
|
import Web3Container, { Web3RenderProps } from 'lib/Web3Container';
|
||||||
|
import { web3Actions } from 'modules/web3';
|
||||||
|
import { AppState } from 'store/reducers';
|
||||||
|
import * as Styled from './styled';
|
||||||
|
|
||||||
interface OwnProps {
|
interface OwnProps {
|
||||||
proposal: ProposalWithCrowdFund;
|
proposal: ProposalWithCrowdFund;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Web3Props {
|
interface StateProps {
|
||||||
web3: Web3RenderProps['web3'];
|
isRefundActionPending: AppState['web3']['isRefundActionPending'];
|
||||||
|
refundActionError: AppState['web3']['refundActionError'];
|
||||||
}
|
}
|
||||||
|
|
||||||
type Props = OwnProps & Web3Props;
|
interface ActionProps {
|
||||||
|
voteRefund: typeof web3Actions['voteRefund'];
|
||||||
|
withdrawRefund: typeof web3Actions['withdrawRefund'];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Web3Props {
|
||||||
|
web3: Web3RenderProps['web3'];
|
||||||
|
account: Web3RenderProps['accounts'][0];
|
||||||
|
}
|
||||||
|
|
||||||
|
type Props = OwnProps & StateProps & ActionProps & Web3Props;
|
||||||
|
|
||||||
class GovernanceRefunds extends React.Component<Props> {
|
class GovernanceRefunds extends React.Component<Props> {
|
||||||
render() {
|
render() {
|
||||||
const fundPct = 32;
|
const { proposal, account, isRefundActionPending, refundActionError } = this.props;
|
||||||
|
const { crowdFund } = proposal;
|
||||||
|
const contributor = crowdFund.contributors.find(c => c.address === account);
|
||||||
|
const isTrustee = crowdFund.trustees.includes(account);
|
||||||
|
const hasVotedForRefund = contributor && contributor.refundVote;
|
||||||
|
const hasRefunded = contributor && contributor.refunded;
|
||||||
|
const refundPct = Math.floor(
|
||||||
|
(crowdFund.amountVotingForRefund / crowdFund.target) * 100,
|
||||||
|
);
|
||||||
|
const color = refundPct < 10 ? '#1890ff' : refundPct < 50 ? '#faad14' : '#f5222d';
|
||||||
|
|
||||||
|
let text;
|
||||||
|
let button;
|
||||||
|
if (!isTrustee && contributor) {
|
||||||
|
if (refundPct < 50) {
|
||||||
|
text = `
|
||||||
|
As a funder of this project, you have the right to vote for a refund. If the
|
||||||
|
amount of funds contributed by refund voters exceeds half of the project's
|
||||||
|
total raised funds, all funders will be able to request refunds.
|
||||||
|
`;
|
||||||
|
if (hasVotedForRefund) {
|
||||||
|
button = {
|
||||||
|
text: 'Undo vote for refund',
|
||||||
|
type: 'danger',
|
||||||
|
onClick: () => this.voteRefund(false),
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
button = {
|
||||||
|
text: 'Vote for refund',
|
||||||
|
type: 'danger',
|
||||||
|
onClick: () => this.voteRefund(true),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (hasRefunded) {
|
||||||
|
return (
|
||||||
|
<Alert
|
||||||
|
type="success"
|
||||||
|
message="Your refund has been processed"
|
||||||
|
description={`
|
||||||
|
We apologize for any inconvenience this propsal has caused you. Please
|
||||||
|
let us know if there's anything we could have done to improve your
|
||||||
|
experience.
|
||||||
|
`}
|
||||||
|
showIcon
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
text = (
|
||||||
|
<>
|
||||||
|
The majority of funders have voted for a refund. Click below to receive your
|
||||||
|
refund.
|
||||||
|
{!crowdFund.isFrozen && (
|
||||||
|
<Alert
|
||||||
|
style={{ marginTop: '1rem' }}
|
||||||
|
type="info"
|
||||||
|
message={`
|
||||||
|
This will require multiple transactions to process, sorry
|
||||||
|
for the inconvenience
|
||||||
|
`}
|
||||||
|
showIcon
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
button = {
|
||||||
|
text: 'Get your refund',
|
||||||
|
type: 'primary',
|
||||||
|
onClick: () => this.withdrawRefund(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (refundPct < 50) {
|
||||||
|
text = `
|
||||||
|
Funders can vote to request refunds. If the amount of funds contributed by
|
||||||
|
refund voters exceeds half of the funds contributed, all funders will be able
|
||||||
|
to request refunds.
|
||||||
|
`;
|
||||||
|
} else {
|
||||||
|
text = `
|
||||||
|
The funders of this project have voted for a refund. All funders can request refunds,
|
||||||
|
and the project will no longer receive any payouts.
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<>
|
||||||
style={{
|
<div style={{ display: 'flex', alignItems: 'center' }}>
|
||||||
display: 'flex',
|
<Styled.ProgressContainer stroke={color}>
|
||||||
alignItems: 'center',
|
<Progress type="dashboard" percent={refundPct} format={p => `${p}%`} />
|
||||||
}}
|
<Styled.ProgressText>voted for a refund</Styled.ProgressText>
|
||||||
>
|
</Styled.ProgressContainer>
|
||||||
<div style={{ textAlign: 'center', marginRight: '2rem' }}>
|
<div>
|
||||||
<Progress
|
<p style={{ fontSize: '1rem' }}>{text}</p>
|
||||||
type="dashboard"
|
{button && (
|
||||||
percent={fundPct}
|
<Button
|
||||||
format={p => `${p}%`}
|
type={button.type as any}
|
||||||
status="exception"
|
onClick={button.onClick}
|
||||||
|
loading={isRefundActionPending}
|
||||||
|
block
|
||||||
|
>
|
||||||
|
{button.text}
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{refundActionError && (
|
||||||
|
<Alert
|
||||||
|
type="error"
|
||||||
|
message="Something went wrong!"
|
||||||
|
description={refundActionError}
|
||||||
|
style={{ margin: '1rem 0 0' }}
|
||||||
|
showIcon
|
||||||
/>
|
/>
|
||||||
<p style={{ opacity: 0.6, fontSize: '0.75rem' }}>voted for a refund</p>
|
)}
|
||||||
</div>
|
</>
|
||||||
<div>
|
|
||||||
<p style={{ fontSize: '1rem' }}>
|
|
||||||
As a funder of this project, you have the right to vote for a refund. If the
|
|
||||||
amount of funds contributed by refund voters exceeds half of the project's
|
|
||||||
total raised funds, a refund will be issued to everyone.
|
|
||||||
</p>
|
|
||||||
<Button type="danger" block>
|
|
||||||
Vote for a Refund
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
voteRefund = (vote: boolean) => {
|
||||||
|
this.props.voteRefund(this.props.proposal.crowdFundContract, vote);
|
||||||
|
};
|
||||||
|
|
||||||
|
withdrawRefund = () => {
|
||||||
|
const { proposal, account } = this.props;
|
||||||
|
this.props.withdrawRefund(proposal.crowdFundContract, account);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ConnectedGovernanceRefunds = connect<StateProps, ActionProps, OwnProps, AppState>(
|
||||||
|
state => ({
|
||||||
|
isRefundActionPending: state.web3.isRefundActionPending,
|
||||||
|
refundActionError: state.web3.refundActionError,
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
voteRefund: web3Actions.voteRefund,
|
||||||
|
withdrawRefund: web3Actions.withdrawRefund,
|
||||||
|
},
|
||||||
|
)(GovernanceRefunds);
|
||||||
|
|
||||||
export default (props: OwnProps) => (
|
export default (props: OwnProps) => (
|
||||||
<Web3Container
|
<Web3Container
|
||||||
renderLoading={() => <Spin />}
|
renderLoading={() => <Spin />}
|
||||||
render={({ web3 }: Web3RenderProps) => <GovernanceRefunds web3={web3} {...props} />}
|
render={({ web3, accounts }: Web3RenderProps) => (
|
||||||
|
<ConnectedGovernanceRefunds web3={web3} account={accounts[0]} {...props} />
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
|
@ -2,6 +2,7 @@ import React from 'react';
|
||||||
import GovernanceMilestones from './Milestones';
|
import GovernanceMilestones from './Milestones';
|
||||||
import GovernanceRefunds from './Refunds';
|
import GovernanceRefunds from './Refunds';
|
||||||
import { ProposalWithCrowdFund } from 'modules/proposals/reducers';
|
import { ProposalWithCrowdFund } from 'modules/proposals/reducers';
|
||||||
|
import Placeholder from 'components/Placeholder';
|
||||||
import * as Styled from './styled';
|
import * as Styled from './styled';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
|
@ -14,10 +15,14 @@ export default class ProposalGovernance extends React.Component<Props> {
|
||||||
|
|
||||||
if (!proposal.crowdFund.isRaiseGoalReached) {
|
if (!proposal.crowdFund.isRaiseGoalReached) {
|
||||||
return (
|
return (
|
||||||
<p>
|
<Placeholder
|
||||||
Milestone history and voting will be displayed here once the project has been
|
style={{ minHeight: '220px' }}
|
||||||
funded.
|
title="Governance isn’t available yet"
|
||||||
</p>
|
subtitle={`
|
||||||
|
Milestone history and voting will be displayed here once the
|
||||||
|
project has been funded
|
||||||
|
`}
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,3 +28,22 @@ export const GovernanceDivider = styled.div`
|
||||||
export const MilestoneActionText = styled.p`
|
export const MilestoneActionText = styled.p`
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
// Shared
|
||||||
|
export const ProgressContainer = styled<{ stroke?: string }, 'div'>('div')`
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
text-align: center;
|
||||||
|
margin: 0 2rem 0.5rem 0;
|
||||||
|
|
||||||
|
.ant-progress-circle-path {
|
||||||
|
stroke: ${p => p.stroke || 'inherit'};
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const ProgressText = styled.div`
|
||||||
|
white-space: nowrap;
|
||||||
|
opacity: 0.6;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
`;
|
||||||
|
|
|
@ -16,6 +16,7 @@ export interface Contributor {
|
||||||
address: string;
|
address: string;
|
||||||
contributionAmount: string;
|
contributionAmount: string;
|
||||||
refundVote: boolean;
|
refundVote: boolean;
|
||||||
|
refunded: boolean;
|
||||||
proportionalContribution: string;
|
proportionalContribution: string;
|
||||||
milestoneNoVotes: boolean[];
|
milestoneNoVotes: boolean[];
|
||||||
}
|
}
|
||||||
|
@ -52,8 +53,10 @@ export interface ProposalMilestone extends Milestone {
|
||||||
|
|
||||||
export interface CrowdFund {
|
export interface CrowdFund {
|
||||||
immediateFirstMilestonePayout: boolean;
|
immediateFirstMilestonePayout: boolean;
|
||||||
|
balance: number;
|
||||||
funded: number;
|
funded: number;
|
||||||
target: number;
|
target: number;
|
||||||
|
amountVotingForRefund: number;
|
||||||
beneficiary: string;
|
beneficiary: string;
|
||||||
deadline: number;
|
deadline: number;
|
||||||
trustees: string[];
|
trustees: string[];
|
||||||
|
|
|
@ -301,3 +301,71 @@ export function voteMilestonePayout(
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function voteRefund(crowdFundContract: any, vote: boolean) {
|
||||||
|
return async (dispatch: Dispatch<any>, getState: GetState) => {
|
||||||
|
dispatch({ type: types.VOTE_REFUND_PENDING });
|
||||||
|
const state = getState();
|
||||||
|
const account = state.web3.accounts[0];
|
||||||
|
|
||||||
|
try {
|
||||||
|
await crowdFundContract.methods
|
||||||
|
.voteRefund(vote)
|
||||||
|
.send({ from: account })
|
||||||
|
.once('confirmation', async () => {
|
||||||
|
await sleep(5000);
|
||||||
|
await dispatch(fetchProposal(crowdFundContract._address));
|
||||||
|
dispatch({ type: types.VOTE_REFUND_FULFILLED });
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
dispatch({
|
||||||
|
type: types.VOTE_REFUND_REJECTED,
|
||||||
|
payload: err.message || err.toString(),
|
||||||
|
error: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function withdrawRefund(crowdFundContract: any, address: string) {
|
||||||
|
return async (dispatch: Dispatch<any>, getState: GetState) => {
|
||||||
|
dispatch({ type: types.WITHDRAW_REFUND_PENDING });
|
||||||
|
const state = getState();
|
||||||
|
const account = state.web3.accounts[0];
|
||||||
|
|
||||||
|
try {
|
||||||
|
let isFrozen = await crowdFundContract.methods.frozen().call({ from: account });
|
||||||
|
if (!isFrozen) {
|
||||||
|
await new Promise(resolve => {
|
||||||
|
crowdFundContract.methods
|
||||||
|
.refund()
|
||||||
|
.send({ from: account })
|
||||||
|
.once('confirmation', async () => {
|
||||||
|
await sleep(5000);
|
||||||
|
isFrozen = await crowdFundContract.methods.frozen().call({ from: account });
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isFrozen) {
|
||||||
|
throw new Error('Proposal isn’t in a refundable state yet.');
|
||||||
|
}
|
||||||
|
|
||||||
|
await crowdFundContract.methods
|
||||||
|
.withdraw(address)
|
||||||
|
.send({ from: account })
|
||||||
|
.once('confirmation', async () => {
|
||||||
|
await sleep(5000);
|
||||||
|
await dispatch(fetchProposal(crowdFundContract._address));
|
||||||
|
dispatch({ type: types.WITHDRAW_REFUND_FULFILLED });
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
dispatch({
|
||||||
|
type: types.WITHDRAW_REFUND_REJECTED,
|
||||||
|
payload: err.message || err.toString(),
|
||||||
|
error: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
|
@ -27,6 +27,9 @@ export interface Web3State {
|
||||||
|
|
||||||
isMilestoneActionPending: boolean;
|
isMilestoneActionPending: boolean;
|
||||||
milestoneActionError: null | string;
|
milestoneActionError: null | string;
|
||||||
|
|
||||||
|
isRefundActionPending: boolean;
|
||||||
|
refundActionError: null | string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const INITIAL_STATE: Web3State = {
|
export const INITIAL_STATE: Web3State = {
|
||||||
|
@ -52,6 +55,9 @@ export const INITIAL_STATE: Web3State = {
|
||||||
|
|
||||||
isMilestoneActionPending: false,
|
isMilestoneActionPending: false,
|
||||||
milestoneActionError: null,
|
milestoneActionError: null,
|
||||||
|
|
||||||
|
isRefundActionPending: false,
|
||||||
|
refundActionError: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
function addContract(state: Web3State, payload: Contract) {
|
function addContract(state: Web3State, payload: Contract) {
|
||||||
|
@ -198,6 +204,27 @@ export default (state = INITIAL_STATE, action: any): Web3State => {
|
||||||
isMilestoneActionPending: false,
|
isMilestoneActionPending: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
case types.VOTE_REFUND_PENDING:
|
||||||
|
case types.WITHDRAW_REFUND_PENDING:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
isRefundActionPending: true,
|
||||||
|
refundActionError: null,
|
||||||
|
};
|
||||||
|
case types.VOTE_REFUND_FULFILLED:
|
||||||
|
case types.WITHDRAW_REFUND_FULFILLED:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
isRefundActionPending: false,
|
||||||
|
};
|
||||||
|
case types.VOTE_REFUND_REJECTED:
|
||||||
|
case types.WITHDRAW_REFUND_REJECTED:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
refundActionError: payload,
|
||||||
|
isRefundActionPending: false,
|
||||||
|
};
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,16 @@ enum web3Types {
|
||||||
VOTE_AGAINST_MILESTONE_PAYOUT_REJECTED = 'VOTE_AGAINST_MILESTONE_PAYOUT_REJECTED',
|
VOTE_AGAINST_MILESTONE_PAYOUT_REJECTED = 'VOTE_AGAINST_MILESTONE_PAYOUT_REJECTED',
|
||||||
VOTE_AGAINST_MILESTONE_PAYOUT_PENDING = 'VOTE_AGAINST_MILESTONE_PAYOUT_PENDING',
|
VOTE_AGAINST_MILESTONE_PAYOUT_PENDING = 'VOTE_AGAINST_MILESTONE_PAYOUT_PENDING',
|
||||||
|
|
||||||
|
VOTE_REFUND = 'VOTE_REFUND',
|
||||||
|
VOTE_REFUND_FULFILLED = 'VOTE_REFUND_FULFILLED',
|
||||||
|
VOTE_REFUND_REJECTED = 'VOTE_REFUND_REJECTED',
|
||||||
|
VOTE_REFUND_PENDING = 'VOTE_REFUND_PENDING',
|
||||||
|
|
||||||
|
WITHDRAW_REFUND = 'WITHDRAW_REFUND',
|
||||||
|
WITHDRAW_REFUND_FULFILLED = 'WITHDRAW_REFUND_FULFILLED',
|
||||||
|
WITHDRAW_REFUND_REJECTED = 'WITHDRAW_REFUND_REJECTED',
|
||||||
|
WITHDRAW_REFUND_PENDING = 'WITHDRAW_REFUND_PENDING',
|
||||||
|
|
||||||
ACCOUNTS = 'ACCOUNTS',
|
ACCOUNTS = 'ACCOUNTS',
|
||||||
ACCOUNTS_FULFILLED = 'ACCOUNTS_FULFILLED',
|
ACCOUNTS_FULFILLED = 'ACCOUNTS_FULFILLED',
|
||||||
ACCOUNTS_REJECTED = 'ACCOUNTS_REJECTED',
|
ACCOUNTS_REJECTED = 'ACCOUNTS_REJECTED',
|
||||||
|
|
|
@ -17,9 +17,11 @@ export async function getCrowdFundState(
|
||||||
const isRaiseGoalReached = await crowdFundContract.methods
|
const isRaiseGoalReached = await crowdFundContract.methods
|
||||||
.isRaiseGoalReached()
|
.isRaiseGoalReached()
|
||||||
.call({ from: account });
|
.call({ from: account });
|
||||||
const funded = isRaiseGoalReached
|
const balance = await web3.eth.getBalance(crowdFundContract._address);
|
||||||
? target
|
const funded = isRaiseGoalReached ? target : balance;
|
||||||
: await web3.eth.getBalance(crowdFundContract._address);
|
const amountVotingForRefund = isRaiseGoalReached
|
||||||
|
? await crowdFundContract.methods.amountVotingForRefund().call({ from: account })
|
||||||
|
: '0';
|
||||||
|
|
||||||
const isFrozen = await crowdFundContract.methods.frozen().call({ from: account });
|
const isFrozen = await crowdFundContract.methods.frozen().call({ from: account });
|
||||||
const trustees = await collectArrayElements<string>(
|
const trustees = await collectArrayElements<string>(
|
||||||
|
@ -115,8 +117,13 @@ export async function getCrowdFundState(
|
||||||
|
|
||||||
return {
|
return {
|
||||||
immediateFirstMilestonePayout,
|
immediateFirstMilestonePayout,
|
||||||
|
// TODO: Bignumber these 4
|
||||||
|
balance: parseFloat(web3.utils.fromWei(String(balance), 'ether')),
|
||||||
funded: parseFloat(web3.utils.fromWei(String(funded), 'ether')),
|
funded: parseFloat(web3.utils.fromWei(String(funded), 'ether')),
|
||||||
target: parseFloat(web3.utils.fromWei(String(target), 'ether')),
|
target: parseFloat(web3.utils.fromWei(String(target), 'ether')),
|
||||||
|
amountVotingForRefund: parseFloat(
|
||||||
|
web3.utils.fromWei(String(amountVotingForRefund), 'ether'),
|
||||||
|
),
|
||||||
beneficiary,
|
beneficiary,
|
||||||
deadline,
|
deadline,
|
||||||
trustees,
|
trustees,
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
"tsc": "tsc",
|
"tsc": "tsc",
|
||||||
"link-contracts": "cd client/lib && ln -s ../../build/contracts contracts",
|
"link-contracts": "cd client/lib && ln -s ../../build/contracts contracts",
|
||||||
"ganache": "ganache-cli -b 5",
|
"ganache": "ganache-cli -b 5",
|
||||||
"truffle": "truffle exec ./bin/init-truffle.js && truffle console"
|
"truffle": "truffle exec ./bin/init-truffle.js && cd client/lib/contracts && truffle console"
|
||||||
},
|
},
|
||||||
"husky": {
|
"husky": {
|
||||||
"hooks": {
|
"hooks": {
|
||||||
|
|
Loading…
Reference in New Issue