Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release / 5.4.400 #3744

Merged
merged 50 commits into from
Nov 20, 2024
Merged
Show file tree
Hide file tree
Changes from 49 commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
8effff3
fix message passing in Firefox
yushih Nov 7, 2024
8f1329c
messaging serialization fix
vsubhuman Oct 20, 2024
a8db808
fix serialization
yushih Oct 23, 2024
2559f75
serialize request data from frontend to the background
yushih Oct 23, 2024
961c736
add error log
yushih Oct 23, 2024
9070b9a
fix FF connector pop out window could not get response for API call t…
yushih Oct 25, 2024
60c1031
parvum melius
yushih Oct 25, 2024
5108345
lint
yushih Oct 29, 2024
a8d6521
log error when UI gets unserializable message
yushih Nov 5, 2024
55cc2e6
sanitized
vsubhuman Nov 8, 2024
04dfbbc
filter message passing
vsubhuman Nov 9, 2024
13252a8
message type checking
vsubhuman Nov 11, 2024
8d4f16d
trace logging fix
vsubhuman Nov 11, 2024
f6be653
fix ttl deserialization
yushih Nov 14, 2024
a0d9123
connector returns user reject when user closes signing popup
yushih Nov 13, 2024
3ff9767
Merge pull request #3738 from Emurgo/fix/YOEXT-1524/connector-sign-re…
vsubhuman Nov 14, 2024
80e1037
Merge pull request #3707 from Emurgo/fix/ff-message-passing
vsubhuman Nov 14, 2024
77bf3f3
add paper wallet page on settings
nistadev Nov 5, 2024
379d5a1
fix eslint & flow errors
nistadev Nov 5, 2024
3354ed0
move button into support/logs section
nistadev Nov 7, 2024
d1e0e46
font size
vsubhuman Nov 15, 2024
8b9f98a
adapt to backend return value change
yushih Nov 14, 2024
2842b2d
allow multiple foreign inputs
yushih Nov 14, 2024
28b630d
function ref fix
vsubhuman Nov 15, 2024
303db73
process multiple items on the api side, not on the caller side
vsubhuman Nov 15, 2024
643ac5c
return fix
vsubhuman Nov 15, 2024
eb9ba57
return fix
vsubhuman Nov 15, 2024
64a667a
lint fix
vsubhuman Nov 15, 2024
a3530f7
Merge pull request #3726 from Emurgo/pat/paper-wallet-settings
vsubhuman Nov 15, 2024
3a3727a
Merge pull request #3741 from Emurgo/ruslan/api-fix-proposal
yushih Nov 15, 2024
88cb124
Trezor wallet governance support
yushih Nov 8, 2024
f3fc415
add comment about unsuppored cert types
yushih Nov 8, 2024
40bdc47
Merge pull request #3739 from Emurgo/fix/connector-sign-foreign-utxo
vsubhuman Nov 15, 2024
08bd3b6
Trezor wallet connector supports some Conway certificate types
yushih Nov 13, 2024
1718dfb
Merge branch 'release/5.4.400' into feat/trezor-conway
vsubhuman Nov 15, 2024
6084c94
package-lock update (post merge)
vsubhuman Nov 15, 2024
72e6100
removed tmp check for trezor
vsubhuman Nov 15, 2024
f5c7592
added support for drep_vkh1
vsubhuman Nov 15, 2024
0cc43ac
Merge pull request #3732 from Emurgo/feat/trezor-conway
vsubhuman Nov 15, 2024
1c5c967
drep ID normalisation to cip129
vsubhuman Nov 15, 2024
940e472
fix module import
vsubhuman Nov 15, 2024
67c6655
Merge remote-tracking branch 'origin/release/5.4.400' into ruslan/dre…
vsubhuman Nov 15, 2024
db97b08
rolling back incorrect import
vsubhuman Nov 17, 2024
192f8a7
trezor drep kind fix
vsubhuman Nov 17, 2024
54d7f9c
safety check for missing drepID
vsubhuman Nov 17, 2024
773cb23
Merge pull request #3742 from Emurgo/ruslan/drep-decoding-update
vsubhuman Nov 18, 2024
528aadd
informing about pre-cip129 drep id on hardware devices
vsubhuman Nov 18, 2024
9b528ab
check for governance participation fix
vsubhuman Nov 19, 2024
6570183
Merge pull request #3745 from Emurgo/ruslan/hw-drep-inform
vsubhuman Nov 19, 2024
998b589
Version bump: 5.4.400
vsubhuman Nov 19, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions .github/workflows/flow-and-lint.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Flow and lint
name: Flow and Lint and TSC

on:
workflow_dispatch:
Expand Down Expand Up @@ -43,4 +43,7 @@ jobs:
npm run flow
- name: lint
run: |
npm run eslint
npm run eslint
- name: tsc
run: |
npm run tsc
Original file line number Diff line number Diff line change
Expand Up @@ -38,17 +38,18 @@ const AccordionDetails = styled(MuiAccordionDetails)(({ theme }: any) => ({
type Props = {
title: string;
content: React.ReactNode;
expanded?: boolean,
};

export const Collapsible = ({ title, content }: Props) => {
const [expanded, setExpanded] = React.useState<any>('none');
export const Collapsible = ({ title, content, expanded: startExpanded }: Props) => {
const [expanded, setExpanded] = React.useState<boolean>(startExpanded ?? false);

const handleChange = (panel: string | false) => (_: React.SyntheticEvent, newExpanded: boolean) => {
setExpanded(newExpanded ? panel : false);
const handleChange = (_: React.SyntheticEvent, newExpanded: boolean) => {
setExpanded(newExpanded);
};

return (
<Accordion disableGutters elevation={0} square expanded={expanded === 'panel1'} onChange={handleChange('panel1')}>
<Accordion disableGutters elevation={0} square expanded={expanded} onChange={handleChange}>
<AccordionSummary
aria-controls="panel1d-content"
id="panel1d-header"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,22 @@ import { FormattedMessage } from 'react-intl';
import globalMessages from '../../../i18n/global-messages';
import { useNavigateTo } from '../../features/governace/common/useNavigateTo';
import { FailedIlustration } from './FailedIlustration';
import LocalizableError from '../../../i18n/LocalizableError';

export const TransactionFailed = () => {
export const TransactionFailed = (props: { error: Error | null }) => {
const navigate = useNavigateTo();
const { error } = props;

return (
<Stack alignItems="center" mt="110px">
<FailedIlustration />
<Typography variant="h5" fontWeight="500" mt={4} mb={1}>
<FormattedMessage {...globalMessages.transactionFailed} />
</Typography>
<Typography variant="body1" mb={2} color="ds.text_gray_low">
<FormattedMessage {...globalMessages.transactionFailedInfo} />
<FormattedMessage {...(
error instanceof LocalizableError ? error : globalMessages.transactionFailedInfo
)}/>
</Typography>
{/* @ts-ignore */}
<Button variant="primary" onClick={() => navigate.selectStatus()}>
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 (Fingerprint):',
defaultMessage: '!!!Drep ID (CIP 129):',
},
delegateToDRep: {
id: 'governance.delegateToDRep',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
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';
import { dRepNormalize } from '../../../../api/ada/lib/cardanoCrypto/utils';
import { unwrapStakingKey } from '../../../../api/ada/lib/storage/bridge/utils';
import { getPrivateStakingKey } from '../../../../api/thunk';
import { DREP_ALWAYS_ABSTAIN, DREP_ALWAYS_NO_CONFIDENCE } from '../common/constants';
import { getFormattedPairingValue } from '../common/helpers';
import { useGovernanceManagerMaker } from '../common/useGovernanceManagerMaker';
import { GovernanceActionType, GovernanceReducer, defaultGovernanceActions, defaultGovernanceState } from './state';
import {hexToBytes} from "../../../tsCoreUtils";

type drepDelegation = { status: string | null; drep: string | null };

Expand Down Expand Up @@ -123,14 +122,14 @@ export const GovernanceContextProvider = ({
});

const governanceStatusState: any = await govApi.getAccountState(stakingKeyHex || '', stakingKeyHex || '');
const { drep, drepKind } = governanceStatusState?.drepDelegation ?? {};

if (governanceStatusState && governanceStatusState.drepDelegation?.drep === 'abstain') {
if (drep === 'abstain') {
setGovernanceStatus({ status: DREP_ALWAYS_ABSTAIN, drep: null });
} else if (governanceStatusState && governanceStatusState.drepDelegation?.drep === 'no_confidence') {
} else if (drep === 'no_confidence') {
setGovernanceStatus({ status: DREP_ALWAYS_NO_CONFIDENCE, drep: null });
} else if (governanceStatusState !== null && governanceStatusState.drepDelegation?.drep.length > 0) {
const words = bech32.toWords(hexToBytes(governanceStatusState.drepDelegation?.drep));
const encoded = bech32.encode('drep', words, 64);
} else if (drep?.length > 0) {
const encoded = dRepNormalize(drep, drepKind);
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 @@ -9,10 +9,12 @@ import { genFormatTokenAmount, genLookupOrFail } from '../../../../../stores/sta
import { Collapsible } from '../../../../components/Collapsible/Collapsible';
import { PasswordInput } from '../../../../components/Input/PasswordInput';
import { DREP_ALWAYS_ABSTAIN, DREP_ALWAYS_NO_CONFIDENCE } from '../../common/constants';
import { dRepNormalize, dRepToPreCip129 } from '../../../../../api/ada/lib/cardanoCrypto/utils';
import { useNavigateTo } from '../../common/useNavigateTo';
import { useStrings } from '../../common/useStrings';
import { useGovernance } from '../../module/GovernanceContextProvider';
import { mapStatus } from '../SelectGovernanceStatus/GovernanceStatusSelection';
import { maybe } from '../../../../../coreUtils'

const Container = styled(Box)(() => ({
paddingTop: '23px',
Expand Down Expand Up @@ -74,9 +76,7 @@ export const DelagationForm = () => {
const strings = useStrings();
const confirmDelegation = async () => {
const response = await checkUserPassword(password);
if (isHardwareWallet) {
signGovernanceTx();
} else if (response?.name === 'WrongPassphraseError') {
if (response?.name === 'WrongPassphraseError') {
setIsIncorectPassword(true);
} else {
signGovernanceTx();
Expand Down Expand Up @@ -111,6 +111,10 @@ export const DelagationForm = () => {
setIsIncorectPassword(false);
}, [password]);

const specifiedDrep = governanceVote.drepID;
const normalizedDrep = maybe(specifiedDrep, dRepNormalize);
const preCip129Drep = maybe(specifiedDrep, dRepToPreCip129);

return (
<Container>
<Stack>
Expand Down Expand Up @@ -138,13 +142,32 @@ export const DelagationForm = () => {
</Typography>
<Box mb="40px">
<Collapsible
expanded={isHardwareWallet}
title={strings.operations}
content={
<TransactionDetails>
{governanceVote.kind === 'delegate' && (
<OperationInfo label={`Delegate voting to ${governanceVote.drepID}`} fee={txFee} />
<OperationInfo label={(
<>
<Typography variant="body1" color="ds.text_gray_medium">
Delegate voting to DRep (CIP 129): {normalizedDrep}
</Typography>
{specifiedDrep !== normalizedDrep ? (
<Typography variant="body1" color="ds.text_gray_medium">
Specified as: {specifiedDrep}
</Typography>
) : null}
{isHardwareWallet && (preCip129Drep !== specifiedDrep) ? (
<Typography variant="body1" color="ds.text_gray_medium">
On a Hardware device this DRep ID might be displayed in old format: {preCip129Drep}
</Typography>
) : null}
</>
)} fee={txFee} />
)}
{governanceVote.kind === DREP_ALWAYS_ABSTAIN && (
<OperationInfo label={strings.selectAbstein} fee={txFee} />
)}
{governanceVote.kind === DREP_ALWAYS_ABSTAIN && <OperationInfo label={strings.selectAbstein} fee={txFee} />}
{governanceVote.kind === DREP_ALWAYS_NO_CONFIDENCE && (
<OperationInfo label={strings.selectNoConfidence} fee={txFee} />
)}
Expand Down Expand Up @@ -186,16 +209,18 @@ export const DelagationForm = () => {
};

type OperationInfoProps = {
label: string;
label: string | JSX.Element;
fee: string;
};

const OperationInfo = ({ label, fee }: OperationInfoProps) => {
return (
<>
<Typography variant="body1" color="ds.text_gray_medium">
{label}
</Typography>
{typeof label === 'string' ? (
<Typography variant="body1" color="ds.text_gray_medium">
{label}
</Typography>
) : label}
<Stack direction="row" justifyContent="space-between">
<Typography variant="body1" fontWeight="500" color="ds.text_gray_normal">
Transaction fee
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ type Props = {
const GovernanceTransactionFailedPage = (props: Props): any => {
return (
<GovernanceLayout {...props}>
<TransactionFailed />
<TransactionFailed error={props.stores.substores.ada.delegationTransaction.error} />
</GovernanceLayout>
);
};
Expand Down
52 changes: 50 additions & 2 deletions packages/yoroi-extension/app/api/ada/lib/cardanoCrypto/utils.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// @flow

import { RustModule } from './rustLoader';
import { bytesToHex, hexToBytes, maybe } from '../../../../coreUtils';
import { base32ToHex } from '../storage/bridge/utils';
import { bytesToHex, fail, forceNonNull, hexToBytes, maybe } from '../../../../coreUtils';
import { base32ToHex, hexToBase32 } from '../storage/bridge/utils';

export function v4PublicToV2(
v4Key: RustModule.WalletV4.Bip32PublicKey
Expand Down Expand Up @@ -58,8 +58,14 @@ export function dRepToMaybeCredentialHex(s: string): ?string {
try {
if (s.startsWith('drep1')) {
if (s.length === 58) {
// CIP129 drep1 encoding is extended value with internal prefix
return maybe(base32ToHex(s), dRepToMaybeCredentialHex);
}
// Pre CIP129 drep1 encoding means same as drep_vkh1 now
return Module.WalletV4.Credential
.from_keyhash(Module.WalletV4.Ed25519KeyHash.from_bech32(s)).to_hex();
}
if (s.startsWith('drep_vkh1')) {
return Module.WalletV4.Credential
.from_keyhash(Module.WalletV4.Ed25519KeyHash.from_bech32(s)).to_hex();
}
Expand All @@ -80,6 +86,48 @@ export function dRepToMaybeCredentialHex(s: string): ?string {
})
}

function parseDrep(drep: string): ?{| hash: string, isScript: boolean |} {
const credentialHex = dRepToMaybeCredentialHex(drep);
if (!credentialHex) {
return null;
}
return RustModule.WasmScope(Module => {
const cred = Module.WalletV4.Credential.from_hex(credentialHex);
const isScript = cred.kind() === Module.WalletV4.CredKind.Script;
const hash = isScript ?
forceNonNull(cred.to_scripthash()).to_hex()
: forceNonNull(cred.to_keyhash()).to_hex();
return { hash, isScript };
})
}

export function dRepNormalize(drep: string, kind?: string): string {
function encodeDrepHash(hash: string, isScript: boolean): string {
// cip129 prefix
const prefix = isScript ? '23' : '22';
return hexToBase32(prefix + hash, 'drep');
}
if (kind != null) {
// drep is hash hex
return encodeDrepHash(drep, kind === 'scripthash');
}
if (drep.startsWith('drep1') && drep.length === 58) {
// drep already cip129
return drep;
}
return maybe(parseDrep(drep), r => encodeDrepHash(r.hash, r.isScript))
?? fail('Failed to normalize drep: ' + drep + ' | kind: ' + String(kind));
}

export function dRepToPreCip129(drep: string): string {
if ((drep.startsWith('drep1') && drep.length < 58) || drep.startsWith('drep_script1')) {
// drep already pre cip129 compatible
return drep;
}
return maybe(parseDrep(drep), r => hexToBase32(r.hash, r.isScript ? 'drep_script' : 'drep'))
?? fail('Failed to normalize drep: ' + drep);
}

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 @@ -551,34 +551,32 @@ export class RemoteFetcher implements IFetcher {

getUtxoData: GetUtxoDataRequest => Promise<GetUtxoDataResponse> = async (body) => {
const { BackendService } = body.network.Backend;
if (body.utxos.length !== 1) {
throw new Error('the RemoteFetcher.getUtxoData expects 1 UTXO');
}
const { txHash, txIndex } = body.utxos[0];
if (BackendService == null) throw new Error(`${nameof(this.getUtxoData)} missing backend url`);
return axios(
`${BackendService}/api/txs/io/${txHash}/o/${txIndex}`,
{
method: 'get',
timeout: 2 * CONFIG.app.walletRefreshInterval,
headers: {
'yoroi-version': this.getLastLaunchVersion(),
'yoroi-locale': this.getCurrentLocale()
}
}
).then(response => [ response.data ])
.catch((error) => {
if (error.response.status === 404 && error.response.data === 'Transaction not found') {
return [ null ];
return Promise.all(body.utxos.map(({ txHash, txIndex }) => {
return axios(
`${BackendService}/api/txs/io/${txHash}/o/${txIndex}`,
{
method: 'get',
timeout: 2 * CONFIG.app.walletRefreshInterval,
headers: {
'yoroi-version': this.getLastLaunchVersion(),
'yoroi-locale': this.getCurrentLocale()
}
}
Logger.error(`${nameof(RemoteFetcher)}::${nameof(this.getUtxoData)} error: ` + stringifyError(error));
throw new GetUtxoDataError();
});
).then(response => response.data)
.catch((error) => {
if (error.response.status === 404 && error.response.data === 'No outputs found') {
return null;
}
Logger.error(`${nameof(RemoteFetcher)}::${nameof(this.getUtxoData)} error: ` + stringifyError(error));
throw new GetUtxoDataError();
});
}));
}

getLatestBlockBySlot: GetLatestBlockBySlotFunc = async (body) => {
const { BackendService } = body.network.Backend;
if (BackendService == null) throw new Error(`${nameof(this.getUtxoData)} missing backend url`);
if (BackendService == null) throw new Error(`${nameof(this.getLatestBlockBySlot)} missing backend url`);
return axios(
`${BackendService}/api/v2.1/lastBlockBySlot`,
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,10 @@ export const base32ToHex = (base32: string): ?string => {
return maybe(base32Words?.words, convertBase32ToHex);
};

export const hexToBase32 = (hex: string, prefix: string): string => {
return bech32Module.encode(prefix, bech32Module.toWords(hexToBytes(hex)));
};

/* eslint-disable */
const bigIntToBase58 = n => {
const base58Alphabet = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
Expand Down
Loading
Loading