Feat/585 Port changes from TFE to Token (#628)

* frontend-monorepo-585: Ensure balances refreshed after disassociation

* frontend-monorepo-585: Add requested state to delegate transaction

* frontend-monorepo-585: Number of decimals can be misleading on vesting form

* frontend-monorepo-585: Decimals not show enough d.p. on vesting page

* frontend-monorepo-585: Render logic of current proposal status

* Update apps/token/.env

Co-authored-by: Dexter Edwards <dexter.edwards93@gmail.com>

* Update apps/token/.env

Co-authored-by: Dexter Edwards <dexter.edwards93@gmail.com>

* frontend-monorepo-585: Changes from PR

Co-authored-by: Dexter Edwards <dexter.edwards93@gmail.com>
This commit is contained in:
Sam Keen 2022-06-24 10:24:59 +01:00 committed by GitHub
parent 994bb4cf2b
commit 3f076660ee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 81 additions and 32 deletions

View File

@ -70,6 +70,7 @@ export interface LockedProgressProps {
leftColor?: string; leftColor?: string;
rightColor?: string; rightColor?: string;
light?: boolean; light?: boolean;
decimals?: number;
} }
export const LockedProgress = ({ export const LockedProgress = ({
@ -81,6 +82,7 @@ export const LockedProgress = ({
leftColor = Colors.vega.pink, leftColor = Colors.vega.pink,
rightColor = Colors.vega.green, rightColor = Colors.vega.green,
light = false, light = false,
decimals = 2,
}: LockedProgressProps) => { }: LockedProgressProps) => {
const lockedPercentage = React.useMemo(() => { const lockedPercentage = React.useMemo(() => {
return locked.div(total).times(100); return locked.div(total).times(100);
@ -117,8 +119,8 @@ export const LockedProgress = ({
</ProgressContents> </ProgressContents>
<ProgressContents light={light}> <ProgressContents light={light}>
<span>{formatNumber(locked, 2)}</span> <span>{formatNumber(locked, decimals)}</span>
<span>{formatNumber(unlocked, 2)}</span> <span>{formatNumber(unlocked, decimals)}</span>
</ProgressContents> </ProgressContents>
</> </>
); );

View File

@ -193,6 +193,7 @@
"noGovernanceTokens": "You need some VEGA tokens to participate in governance", "noGovernanceTokens": "You need some VEGA tokens to participate in governance",
"youVoted": "You voted", "youVoted": "You voted",
"changeVote": "Change vote", "changeVote": "Change vote",
"voteRequested": "Please confirm transaction in wallet",
"votePending": "Casting vote", "votePending": "Casting vote",
"voteError": "Something went wrong, and your vote was not seen by the network", "voteError": "Something went wrong, and your vote was not seen by the network",
"back": "back", "back": "back",
@ -280,6 +281,7 @@
"stakingHasAssociated": "You have {{tokens}} $VEGA tokens associated.", "stakingHasAssociated": "You have {{tokens}} $VEGA tokens associated.",
"stakingAssociateMoreButton": "Associate more $VEGA tokens with wallet", "stakingAssociateMoreButton": "Associate more $VEGA tokens with wallet",
"stakingDisassociateButton": "Disassociate $VEGA tokens from wallet", "stakingDisassociateButton": "Disassociate $VEGA tokens from wallet",
"stakingConfirm": "Open you wallet app to confirm",
"associateButton": "Associate $VEGA tokens with wallet", "associateButton": "Associate $VEGA tokens with wallet",
"nodeQueryFailed": "Could not get data for validator {{node}}", "nodeQueryFailed": "Could not get data for validator {{node}}",
"stakeAddPendingTitle": "Adding {{amount}} $VEGA to validator {{node}}", "stakeAddPendingTitle": "Adding {{amount}} $VEGA to validator {{node}}",
@ -540,5 +542,8 @@
"numberOfAgainstVotes": "Number of votes against", "numberOfAgainstVotes": "Number of votes against",
"yesPercentage": "Yes percentage", "yesPercentage": "Yes percentage",
"noPercentage": "No percentage", "noPercentage": "No percentage",
"proposalTerms": "Proposal terms" "proposalTerms": "Proposal terms",
"currentlySetTo": "Currently set to ",
"pass": "Pass",
"fail": "Fail"
} }

View File

@ -34,30 +34,22 @@ export const CurrentProposalStatus = ({
{ addSuffix: true } { addSuffix: true }
); );
if (proposal.state === ProposalState.Open && willPass) { if (proposal.state === ProposalState.Open) {
return <StatusPass>{t('shouldPass')}</StatusPass>; if (willPass) {
} return (
<>
if (!participationMet) { {t('currentlySetTo')}
return ( <StatusPass>{t('pass')}</StatusPass>
<> </>
<span>{t('voteFailedReason')}</span> );
<span className="current-proposal-status__fail"> } else {
{t('participationNotMet')} return (
</span> <>
<span>&nbsp;{daysClosedAgo}.</span> {t('currentlySetTo')}
</> <StatusFail>{t('fail')}</StatusFail>
); </>
} );
}
if (!majorityMet) {
return (
<>
<span>{t('voteFailedReason')}</span>
<StatusFail>{t('majorityNotMet')}</StatusFail>
<span>&nbsp;{daysClosedAgo}.</span>
</>
);
} }
if ( if (
@ -65,6 +57,26 @@ export const CurrentProposalStatus = ({
proposal.state === ProposalState.Declined || proposal.state === ProposalState.Declined ||
proposal.state === ProposalState.Rejected proposal.state === ProposalState.Rejected
) { ) {
if (!participationMet) {
return (
<>
<span>{t('voteFailedReason')}</span>
<StatusFail>{t('participationNotMet')}</StatusFail>
<span>&nbsp;{daysClosedAgo}.</span>
</>
);
}
if (!majorityMet) {
return (
<>
<span>{t('voteFailedReason')}</span>
<StatusFail>{t('majorityNotMet')}</StatusFail>
<span>&nbsp;{daysClosedAgo}.</span>
</>
);
}
return ( return (
<> <>
<span>{t('voteFailedReason')}</span> <span>{t('voteFailedReason')}</span>

View File

@ -17,6 +17,7 @@ export enum VoteState {
NotCast = 'NotCast', NotCast = 'NotCast',
Yes = 'Yes', Yes = 'Yes',
No = 'No', No = 'No',
Requested = 'Requested',
Pending = 'Pending', Pending = 'Pending',
Failed = 'Failed', Failed = 'Failed',
} }
@ -69,7 +70,7 @@ export function useUserVote(
} }
}, [userVote]); }, [userVote]);
// Start a starts a timeout of 30s to set a failed message if // Starts a timeout of 30s to set a failed message if
// the vote is not seen by the time the callback is invoked // the vote is not seen by the time the callback is invoked
React.useEffect(() => { React.useEffect(() => {
// eslint-disable-next-line // eslint-disable-next-line
@ -93,7 +94,7 @@ export function useUserVote(
async function castVote(value: VoteValue) { async function castVote(value: VoteValue) {
if (!proposalId || !keypair) return; if (!proposalId || !keypair) return;
setVoteState(VoteState.Pending); setVoteState(VoteState.Requested);
try { try {
const variables = { const variables = {
@ -105,6 +106,7 @@ export function useUserVote(
}, },
}; };
await sendTx(variables); await sendTx(variables);
setVoteState(VoteState.Pending);
// Now await vote via poll in parent component // Now await vote via poll in parent component
} catch (err) { } catch (err) {

View File

@ -124,6 +124,10 @@ export const VoteButtons = ({
return <p>{cantVoteUI}</p>; return <p>{cantVoteUI}</p>;
} }
if (voteState === VoteState.Requested) {
return <p>{t('voteRequested')}...</p>;
}
if (voteState === VoteState.Pending) { if (voteState === VoteState.Pending) {
return <p>{t('votePending')}...</p>; return <p>{t('votePending')}...</p>;
} }

View File

@ -49,7 +49,7 @@ export const VoteDetails = ({ proposal }: VoteDetailsProps) => {
<span> <span>
<CurrentProposalStatus proposal={proposal} /> <CurrentProposalStatus proposal={proposal} />
</span> </span>
.&nbsp; {'. '}
{proposal.state === ProposalState.Open ? daysLeft : null} {proposal.state === ProposalState.Open ? daysLeft : null}
</p> </p>
<table className="w-full font-normal mb-12"> <table className="w-full font-normal mb-12">

View File

@ -76,6 +76,7 @@ export const TrancheItem = ({
total={total} total={total}
leftLabel={t('Locked')} leftLabel={t('Locked')}
rightLabel={t('Unlocked')} rightLabel={t('Unlocked')}
decimals={18}
/> />
<div className="text-right" data-testid="tranche-item-footer"> <div className="text-right" data-testid="tranche-item-footer">

View File

@ -8,6 +8,7 @@ import {
} from '../../../components/staking-method-radio'; } from '../../../components/staking-method-radio';
import { TxState } from '../../../hooks/transaction-reducer'; import { TxState } from '../../../hooks/transaction-reducer';
import { useSearchParams } from '../../../hooks/use-search-params'; import { useSearchParams } from '../../../hooks/use-search-params';
import { useRefreshAssociatedBalances } from '../../../hooks/use-refresh-associated-balances';
import { ContractDisassociate } from './contract-disassociate'; import { ContractDisassociate } from './contract-disassociate';
import { DisassociateTransaction } from './disassociate-transaction'; import { DisassociateTransaction } from './disassociate-transaction';
import { useRemoveStake } from './hooks'; import { useRemoveStake } from './hooks';
@ -26,6 +27,7 @@ export const DisassociatePage = ({
const [amount, setAmount] = React.useState<string>(''); const [amount, setAmount] = React.useState<string>('');
const [selectedStakingMethod, setSelectedStakingMethod] = const [selectedStakingMethod, setSelectedStakingMethod] =
React.useState<StakingMethod | null>(params.method || null); React.useState<StakingMethod | null>(params.method || null);
const refreshBalances = useRefreshAssociatedBalances();
// Clear the amount when the staking method changes // Clear the amount when the staking method changes
React.useEffect(() => { React.useEffect(() => {
@ -38,6 +40,12 @@ export const DisassociatePage = ({
perform: txPerform, perform: txPerform,
} = useRemoveStake(address, amount, vegaKey.pub, selectedStakingMethod); } = useRemoveStake(address, amount, vegaKey.pub, selectedStakingMethod);
React.useEffect(() => {
if (txState.txState === TxState.Complete) {
refreshBalances(address, vegaKey.pub);
}
}, [txState, refreshBalances, address, vegaKey.pub]);
if (txState.txState !== TxState.Default) { if (txState.txState !== TxState.Default) {
return ( return (
<DisassociateTransaction <DisassociateTransaction

View File

@ -18,7 +18,14 @@ import type {
import { StakeFailure } from './stake-failure'; import { StakeFailure } from './stake-failure';
import { StakePending } from './stake-pending'; import { StakePending } from './stake-pending';
import { StakeSuccess } from './stake-success'; import { StakeSuccess } from './stake-success';
import { Button, FormGroup, RadioGroup, Radio } from '@vegaprotocol/ui-toolkit'; import {
Button,
Callout,
FormGroup,
Intent,
Radio,
RadioGroup,
} from '@vegaprotocol/ui-toolkit';
import { useVegaWallet } from '@vegaprotocol/wallet'; import { useVegaWallet } from '@vegaprotocol/wallet';
import type { import type {
DelegateSubmissionBody, DelegateSubmissionBody,
@ -46,6 +53,7 @@ export const PARTY_DELEGATIONS_QUERY = gql`
enum FormState { enum FormState {
Default, Default,
Requested,
Pending, Pending,
Success, Success,
Failure, Failure,
@ -115,7 +123,7 @@ export const StakingForm = ({
}, [action, availableStakeToAdd, availableStakeToRemove]); }, [action, availableStakeToAdd, availableStakeToRemove]);
async function onSubmit() { async function onSubmit() {
setFormState(FormState.Pending); setFormState(FormState.Requested);
const delegateInput: DelegateSubmissionBody = { const delegateInput: DelegateSubmissionBody = {
pubKey: pubkey, pubKey: pubkey,
propagate: true, propagate: true,
@ -139,6 +147,7 @@ export const StakingForm = ({
try { try {
const command = action === Actions.Add ? delegateInput : undelegateInput; const command = action === Actions.Add ? delegateInput : undelegateInput;
await sendTx(command); await sendTx(command);
setFormState(FormState.Pending);
// await success via poll // await success via poll
} catch (err) { } catch (err) {
@ -184,6 +193,12 @@ export const StakingForm = ({
if (formState === FormState.Failure) { if (formState === FormState.Failure) {
return <StakeFailure nodeName={nodeName} />; return <StakeFailure nodeName={nodeName} />;
} else if (formState === FormState.Requested) {
return (
<Callout title="Confirm transaction in wallet" intent={Intent.Warning}>
<p>{t('stakingConfirm')}</p>
</Callout>
);
} else if (formState === FormState.Pending) { } else if (formState === FormState.Pending) {
return <StakePending action={action} amount={amount} nodeName={nodeName} />; return <StakePending action={action} amount={amount} nodeName={nodeName} />;
} else if (formState === FormState.Success) { } else if (formState === FormState.Success) {