Skip to content

Commit

Permalink
Merge pull request #3613 from Emurgo/release/5.3.100
Browse files Browse the repository at this point in the history
Release / 5.3.100
  • Loading branch information
vsubhuman authored Sep 2, 2024
2 parents e32b97c + 2f54503 commit 09a5073
Show file tree
Hide file tree
Showing 18 changed files with 423 additions and 124 deletions.
Original file line number Diff line number Diff line change
@@ -1,42 +1,35 @@
import Button from '@mui/material/Button';
import { LoadingButton } from '@mui/lab';
import Stack from '@mui/material/Stack';
import Typography from '@mui/material/Typography';
import { parseDrepId } from '@yoroi/staking';
import * as React from 'react';
import { RustModule } from '../../../../api/ada/lib/cardanoCrypto/rustLoader';
import { dRepToMaybeCredentialHex } from '../../../../api/ada/lib/cardanoCrypto/utils';
import { TextInput } from '../../../components/Input/TextInput';
import { useModal } from '../../../components/modals/ModalContext';
import { useGovernance } from '../module/GovernanceContextProvider';
import { useStrings } from './useStrings';

type ChooseDRepModallProps = {
onSubmit?: (drepId: string) => void;
onSubmit?: (drepId: string, drepCredential: string) => void;
};

export const ChooseDRepModal = ({ onSubmit }: ChooseDRepModallProps) => {
const [drepId, setDrepId] = React.useState('');
const [error, setError] = React.useState(false);

const { dRepIdChanged, governanceVoteChanged } = useGovernance();
const { isLoading } = useModal();
const strings = useStrings();

// TODO hook endpoint not working well
// const { error, isFetched, isFetching } = useIsValidDRepID(drepId, {
// retry: false,
// enabled: drepId.length > 0,
// });

React.useEffect(() => {
setError(false);
}, [drepId]);

const confirmDRep = () => {
parseDrepId(drepId, RustModule.CrossCsl.init('any'))
.then(_ => {
onSubmit?.(drepId);
})
.catch(_ => {
setError(true);
});
const dRepCredentialHex: string | null = dRepToMaybeCredentialHex(drepId);
if (dRepCredentialHex == null) {
setError(true);
} else {
onSubmit?.(drepId, dRepCredentialHex);
}
};

return (
Expand All @@ -57,13 +50,18 @@ export const ChooseDRepModal = ({ onSubmit }: ChooseDRepModallProps) => {
value={drepId}
error={error}
helperText={error ? strings.incorectFormat : ' '}
// defaultValue="drep1wn0dklu87w8d9pkuyr7jalulgvl9w2he0hn0fne9k5a6y4d55mt"
/>
</Stack>
{/* @ts-ignore */}
<Button onClick={confirmDRep} fullWidth variant="primary" disabled={error || drepId.length === 0}>
<LoadingButton
loading={isLoading}
onClick={confirmDRep}
fullWidth
// @ts-ignore
variant="primary"
disabled={error || drepId.length === 0}
>
{strings.confirm}
</Button>
</LoadingButton>
</Stack>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import CardContent from '@mui/material/CardContent';
import Typography from '@mui/material/Typography';
import { styled } from '@mui/material/styles';
import * as React from 'react';
import LoadingSpinner from '../../../../components/widgets/LoadingSpinner';
import { useGovernance } from '../module/GovernanceContextProvider';

type Props = {
title: string;
Expand All @@ -14,9 +16,10 @@ type Props = {
selected: boolean;
onClick: () => void;
pending: boolean;
loading: boolean;
};

const StyledCard: any = styled(Stack)(({ theme, selected, pending }: any) => ({
const StyledCard: any = styled(Stack)(({ theme, selected, pending, isDrepSelected }: any) => ({
position: 'relative',
display: 'flex',
flexDirection: 'column',
Expand All @@ -33,6 +36,7 @@ const StyledCard: any = styled(Stack)(({ theme, selected, pending }: any) => ({
...(selected && {
background: !pending && theme.palette.ds.bg_gradient_2,
border: 'none',
pointerEvents: !isDrepSelected && 'none',
}),
cursor: 'pointer',
...(pending && {
Expand All @@ -56,11 +60,11 @@ const Description = styled(Typography)(({ theme }) => ({
marginTop: theme.spacing(1),
}));

// const SpinnerBox = styled(Box)(() => ({
// position: 'absolute',
// right: 15,
// top: 15,
// }));
const SpinnerBox = styled(Box)(() => ({
position: 'absolute',
right: 15,
top: 15,
}));

export const GovernanceVoteingCard = ({
title,
Expand All @@ -71,17 +75,23 @@ export const GovernanceVoteingCard = ({
selected,
onClick,
pending = false,
loading = false,
}: Props) => {
const [hover, onHover] = React.useState(false);

const { governanceStatus } = useGovernance();
return (
<div onMouseOver={() => onHover(true)} onMouseLeave={() => onHover(false)}>
<StyledCard onClick={pending ? undefined : onClick} pending={pending === true ? 'true' : undefined} selected={selected}>
{/* {pending && selected && (
<StyledCard
onClick={pending ? undefined : onClick}
pending={pending === true ? 'true' : undefined}
selected={selected}
isDrepSelected={governanceStatus.status === 'delegate'}
>
{loading && (
<SpinnerBox>
<LoadingSpinner />
</SpinnerBox>
)} */}
)}
<CardContent>
<IconContainer>{icon}</IconContainer>
<Typography variant="h3" fontWeight="500" mt="16px">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import BigNumber from 'bignumber.js';
import moment from 'moment';
import { WalletTypeOption } from '../../../../api/ada/lib/storage/models/ConceptualWallet/interfaces';
import { maybe } from '../../../../coreUtils';
import { genLookupOrFail } from '../../../../stores/stateless/tokenHelpers';
import { calculateAndFormatValue } from '../../../../utils/unit-of-account';

Expand Down Expand Up @@ -89,14 +88,17 @@ export const getFormattedPairingValue = (getCurrentPrice, defaultTokenInfo, unit
};

const getTotalAmount = (walletAmount, rewards) => {
return maybe(walletAmount, w => rewards.joinAddCopy(w));
return walletAmount && rewards
? walletAmount.joinAddCopy(rewards)
: (walletAmount ?? rewards);
};

const getWalletTotalAdaBalance = (stores, selectedWallet) => {
const totalAmount = stores.transactions.getBalance(selectedWallet);
const rewards = stores.delegation.getRewardBalanceOrZero(selectedWallet);
const amount = getTotalAmount(totalAmount, rewards);
const defaultEntry = amount?.getDefaultEntry();
if (defaultEntry == null) return new BigNumber(0);
const getTokenInfo = genLookupOrFail(stores.tokenInfoStore.tokenInfo);
const tokenInfo = getTokenInfo(defaultEntry);
return defaultEntry.amount.shiftedBy(-tokenInfo.Metadata.numberOfDecimals);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export const messages = Object.freeze(
},
drepId: {
id: 'governance.drepId',
defaultMessage: '!!!Drep ID:',
defaultMessage: '!!!Drep ID (Fingerprint):',
},
delegateToDRep: {
id: 'governance.delegateToDRep',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { GovernanceApi } from '@emurgo/yoroi-lib/dist/governance/emurgo-api';
import { bech32 } from 'bech32';
import * as React from 'react';

import { RustModule } from '../../../../api/ada/lib/cardanoCrypto/rustLoader';
Expand Down Expand Up @@ -141,7 +142,9 @@ export const GovernanceContextProvider = ({
} else if (governanceStatusState && governanceStatusState.drepDelegation?.drep === 'no_confidence') {
setGovernanceStatus({ status: DREP_ALWAYS_NO_CONFIDENCE, drep: null });
} else if (governanceStatusState !== null && governanceStatusState.drepDelegation?.drep.length > 0) {
setGovernanceStatus({ status: 'delegate', drep: governanceStatusState.drepDelegation?.drep || null });
const words = bech32.toWords(Buffer.from(governanceStatusState.drepDelegation?.drep, 'hex'));
const encoded = bech32.encode('drep', words, 64);
setGovernanceStatus({ status: 'delegate', drep: encoded || null });
} else {
setGovernanceStatus({ status: 'none', drep: null });
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,17 +42,19 @@ export const GovernanceStatusSelection = () => {
walletAdaBalance,
triggerBuySellAdaDialog,
submitedTransactions,
governanceVote,
} = useGovernance();
const [error, setError] = React.useState<string | null>(null);
const [loadingUnsignTx, setLoadingUnsignTx] = React.useState<boolean>(false);
const navigateTo = useNavigateTo();
const strings = useStrings();
const { openModal, closeModal } = useModal();
const { openModal, closeModal, startLoading } = useModal();
const pageTitle = governanceStatus.status !== 'none' ? strings.governanceStatus : strings.registerGovernance;
const statusRawText = mapStatus[governanceStatus.status || ''];
const pageSubtitle = governanceStatus.status === 'none' ? strings.reviewSelection : strings.statusSelected(statusRawText);
const isPendindDrepDelegationTx = submitedTransactions.length > 0 && submitedTransactions[0]?.isDrepDelegation === true;

const openDRepIdModal = (onSubmit: (drepID: string) => void) => {
const openDRepIdModal = (onSubmit: (drepID: string, drepCredential: string) => void) => {
if (!governanceManager) {
return;
}
Expand All @@ -65,40 +67,46 @@ export const GovernanceStatusSelection = () => {
),
width: '648px',
height: '336px',
isLoading: loadingUnsignTx,
});
};

const handleDelegate = async () => {
openDRepIdModal(drepID => {
openDRepIdModal((drepID, drepCredential) => {
const vote: Vote = { kind: 'delegate', drepID };
createUnsignTx(drepID);
governanceVoteChanged(vote);
createUnsignTx(drepCredential);
});
};

const handleAbstain = async () => {
await createUnsignTx(DREP_ALWAYS_ABSTAIN);
const vote: Vote = { kind: DREP_ALWAYS_ABSTAIN };
governanceVoteChanged(vote);
await createUnsignTx(DREP_ALWAYS_ABSTAIN);
};

const handleNoConfidence = async () => {
await createUnsignTx(DREP_ALWAYS_NO_CONFIDENCE);
const vote: Vote = { kind: DREP_ALWAYS_NO_CONFIDENCE };
governanceVoteChanged(vote);
await createUnsignTx(DREP_ALWAYS_NO_CONFIDENCE);
};

const createUnsignTx = async kind => {
try {
await createDrepDelegationTransaction(kind);
setError(null);
navigateTo.delegationForm();
setLoadingUnsignTx(true);
startLoading();
setTimeout(async () => {
await createDrepDelegationTransaction(kind);
navigateTo.delegationForm();
setLoadingUnsignTx(false);
setError(null);
}, 200);
} catch (e) {
setError('Error trying to Vote. Please try again later');
closeModal();
setLoadingUnsignTx(false);
}
};

const optionsList = [
{
title: governanceStatus.status === 'delegate' ? strings.delegatingToDRep : strings.delegateToDRep,
Expand All @@ -111,23 +119,26 @@ export const GovernanceStatusSelection = () => {
icon: <DRepIlustration />,
selected: governanceStatus.status === 'delegate' ? true : false,
onClick: handleDelegate,
pending: isPendindDrepDelegationTx,
pending: isPendindDrepDelegationTx || loadingUnsignTx,
loading: loadingUnsignTx && governanceVote.kind === 'delegate',
},
{
title: strings.abstain,
description: strings.abstainInfo,
icon: <Abstein />,
selected: governanceStatus.status === DREP_ALWAYS_ABSTAIN ? true : false,
onClick: handleAbstain,
pending: isPendindDrepDelegationTx,
pending: isPendindDrepDelegationTx || loadingUnsignTx,
loading: loadingUnsignTx && governanceVote.kind === DREP_ALWAYS_ABSTAIN,
},
{
title: strings.noConfidence,
description: strings.noConfidenceInfo,
icon: <NoConfidance />,
selected: governanceStatus.status === DREP_ALWAYS_NO_CONFIDENCE ? true : false,
onClick: handleNoConfidence,
pending: isPendindDrepDelegationTx,
pending: isPendindDrepDelegationTx || loadingUnsignTx,
loading: loadingUnsignTx && governanceVote.kind === DREP_ALWAYS_NO_CONFIDENCE,
},
];

Expand Down Expand Up @@ -170,6 +181,7 @@ export const GovernanceStatusSelection = () => {
selected={option.selected}
onClick={option.onClick}
pending={option.pending}
loading={option.loading}
/>
);
})
Expand Down
16 changes: 16 additions & 0 deletions packages/yoroi-extension/app/api/ada/lib/cardanoCrypto/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,22 @@ export function transactionHexReplaceWitnessSet(txHex: string, witnessSetHex: st
});
}

export function dRepToMaybeCredentialHex(s: string): ?string {
return RustModule.WasmScope(Module => {
try {
if (s.startsWith('drep1')) {
return Module.WalletV4.Credential
.from_keyhash(Module.WalletV4.Ed25519KeyHash.from_bech32(s)).to_hex();
}
if (s.startsWith('drep_script1')) {
return Module.WalletV4.Credential
.from_scripthash(Module.WalletV4.ScriptHash.from_bech32(s)).to_hex();
}
} catch {} // eslint-disable-line no-empty
return null;
})
}

export function pubKeyHashToRewardAddress(hex: string, network: number): string {
return RustModule.WasmScope(Module =>
Module.WalletV4.RewardAddress.new(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import { normalizeToAddress, unwrapStakingKey, } from './utils';
import type { IGetAllUtxosResponse, IGetStakingKey, } from '../models/PublicDeriver/interfaces';
import { MultiToken, } from '../../../../common/lib/MultiToken';
import { maybe, fail } from '../../../../../coreUtils';
import { isHex } from '@emurgo/yoroi-lib/dist/internals/utils/index';

export type GetDelegatedBalanceRequest = {|
publicDeriver: PublicDeriver<> & IGetStakingKey,
Expand Down Expand Up @@ -139,23 +138,20 @@ export async function getUtxoDelegatedBalance(
export const DREP_ALWAYS_ABSTAIN = 'ALWAYS_ABSTAIN';
export const DREP_ALWAYS_NO_CONFIDENCE = 'ALWAYS_NO_CONFIDENCE';

// <TODO:WASM_MONAD>
function parseKey(key: string): RustModule.WalletV4.Ed25519KeyHash {
return isHex(key)
? RustModule.WalletV4.Ed25519KeyHash.from_hex(key)
: RustModule.WalletV4.Ed25519KeyHash.from_bech32(key);
}

// <TODO:WASM_MONAD>
function parseDrep(drepCredential: string): RustModule.WalletV4.DRep {
const DRep = RustModule.WalletV4.DRep;
if (drepCredential === DREP_ALWAYS_ABSTAIN) return DRep.new_always_abstain();
if (drepCredential === DREP_ALWAYS_NO_CONFIDENCE) return DRep.new_always_no_confidence();
// <TODO:FIX> to handle script hashes
const credential = RustModule.WalletV4.Credential.from_keyhash(parseKey(drepCredential));
return maybe(credential.to_keyhash(), k => DRep.new_key_hash(k))
?? maybe(credential.to_scripthash(), s => DRep.new_script_hash(s))
?? fail('weird credential cannot be converted into a drep: ' + credential.to_hex())
try {
const DRep = RustModule.WalletV4.DRep;
if (drepCredential === DREP_ALWAYS_ABSTAIN) return DRep.new_always_abstain();
if (drepCredential === DREP_ALWAYS_NO_CONFIDENCE) return DRep.new_always_no_confidence();
const credential = RustModule.WalletV4.Credential.from_hex(drepCredential);
return maybe(credential.to_keyhash(), k => DRep.new_key_hash(k))
?? maybe(credential.to_scripthash(), s => DRep.new_script_hash(s))
?? fail('weird credential cannot be converted into a drep: ' + credential.to_hex())
} catch (e) {
console.log('Fail to parse a drep credential: ' + drepCredential, e);
throw e;
}
}

// <TODO:WASM_MONAD>
Expand Down
Loading

0 comments on commit 09a5073

Please sign in to comment.