Skip to content

Commit

Permalink
feat: cardano review modal with governance
Browse files Browse the repository at this point in the history
fix: modal heading

fix: text

Update packages/suite/src/components/suite/modals/ReduxModal/CardanoWithdrawModal.tsx

Co-authored-by: Marek Mahut <[email protected]>

review

fix: new modal
  • Loading branch information
vladimirvolek committed Jan 3, 2025
1 parent 560819f commit 2a0724b
Show file tree
Hide file tree
Showing 24 changed files with 309 additions and 59 deletions.
16 changes: 16 additions & 0 deletions packages/blockchain-link-types/src/blockfrost.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,22 @@ export interface BlockfrostAccountInfo {
total: number;
index: number;
};
misc: {
staking: {
address: string;
isActive: boolean;
rewards: string;
poolId: string | null;
drep: {
drep_id: string;
hex: string;
amount: string;
active: boolean;
active_epoch: number | null;
has_script: boolean;
} | null;
};
};
}

export interface ParseAssetResult {
Expand Down
8 changes: 8 additions & 0 deletions packages/blockchain-link-types/src/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,14 @@ export interface AccountInfo {
isActive: boolean;
rewards: string;
poolId: string | null;
drep: {
drep_id: string;
hex: string;
amount: string;
active: boolean;
active_epoch: number | null;
has_script: boolean;
} | null;
};
// SOL
owner?: string; // The Solana program owning the account
Expand Down
64 changes: 44 additions & 20 deletions packages/suite/src/actions/wallet/cardanoStakingActions.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,34 @@
import { getUnixTime } from 'date-fns';

import { BlockchainBlock } from '@trezor/connect';
import { CARDANO_STAKE_POOL_PREVIEW_URL, CARDANO_STAKE_POOL_MAINNET_URL } from '@trezor/urls';
import { isPending, getAccountTransactions } from '@suite-common/wallet-utils';
import {
CARDANO_STAKE_POOL_PREVIEW_URL,
CARDANO_STAKE_POOL_MAINNET_URL,
CARDANO_MAINNET_DREP,
CARDANO_PREVIEW_DREP,
} from '@trezor/urls';
import { isPending, getAccountTransactions, getNetworkName } from '@suite-common/wallet-utils';
import { CARDANO_DEFAULT_TTL_OFFSET } from '@suite-common/wallet-constants';
import { transactionsActions } from '@suite-common/wallet-core';
import { getNetworkOptional } from '@suite-common/wallet-config';

import { CARDANO_STAKING } from 'src/actions/wallet/constants';
import { PendingStakeTx, PoolsResponse, CardanoNetwork } from 'src/types/wallet/cardanoStaking';
import {
PendingStakeTx,
PoolsResponse,
CardanoNetwork,
DRepResponse,
} from 'src/types/wallet/cardanoStaking';
import { Account, WalletAccountTransaction } from 'src/types/wallet';
import { Dispatch, GetState } from 'src/types/suite';

export type CardanoStakingAction =
| { type: typeof CARDANO_STAKING.ADD_PENDING_STAKE_TX; pendingStakeTx: PendingStakeTx }
| { type: typeof CARDANO_STAKING.REMOVE_PENDING_STAKE_TX; accountKey: string }
| {
type: typeof CARDANO_STAKING.SET_TREZOR_POOLS;
type: typeof CARDANO_STAKING.SET_TREZOR_DATA;
trezorPools: PoolsResponse;
trezorDRep: DRepResponse;
network: CardanoNetwork;
}
| { type: typeof CARDANO_STAKING.SET_FETCH_ERROR; error: boolean; network: CardanoNetwork }
Expand Down Expand Up @@ -102,34 +113,47 @@ export const validatePendingStakeTxOnTx =
}
};

export const fetchTrezorPools = (network: 'ADA' | 'tADA') => async (dispatch: Dispatch) => {
const cardanoNetwork = network === 'ADA' ? 'mainnet' : 'preview';
export const fetchTrezorData = (network: 'ADA' | 'tADA') => async (dispatch: Dispatch) => {
const cardanoNetwork = getNetworkName(network);

dispatch({
type: CARDANO_STAKING.SET_FETCH_LOADING,
loading: true,
network: cardanoNetwork,
});

// Fetch ID of Trezor stake pool that will be used in delegation transaction
const url =
cardanoNetwork === 'mainnet'
? CARDANO_STAKE_POOL_MAINNET_URL
: CARDANO_STAKE_POOL_PREVIEW_URL;

try {
const response = await fetch(url, { credentials: 'same-origin' });
const responseJson = await response.json();

if (!responseJson || !('next' in responseJson) || !('pools' in responseJson)) {
// todo: even if this happens, error will be overridden by this bug
// https://github.com/trezor/trezor-suite/issues/5485
// Fetch ID of Trezor stake pool that will be used in delegation transaction
const urlPools =
cardanoNetwork === 'mainnet'
? CARDANO_STAKE_POOL_MAINNET_URL
: CARDANO_STAKE_POOL_PREVIEW_URL;

const responsePools = await fetch(urlPools, { credentials: 'same-origin' });
const responsePoolsJson = await responsePools.json();

if (
!responsePoolsJson ||
!('next' in responsePoolsJson) ||
!('pools' in responsePoolsJson)
) {
throw new Error('Cardano: fetchTrezorPools: Invalid data format');
}

// Fetch DRep for transaction withdrawal
const urlDRep = cardanoNetwork === 'mainnet' ? CARDANO_MAINNET_DREP : CARDANO_PREVIEW_DREP;

const responseDRep = await fetch(urlDRep, { credentials: 'same-origin' });
const responseDRepJson = await responseDRep.json();

if (!responseDRepJson || !('drep' in responseDRepJson)) {
throw new Error('Cardano: fetchTrezorDRep: Invalid data format');
}

dispatch({
type: CARDANO_STAKING.SET_TREZOR_POOLS,
trezorPools: responseJson as PoolsResponse,
type: CARDANO_STAKING.SET_TREZOR_DATA,
trezorPools: responsePoolsJson as PoolsResponse,
trezorDRep: responseDRepJson as DRepResponse,
network: cardanoNetwork,
});
} catch {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export const ADD_PENDING_STAKE_TX = '@cardano-staking/set-pending-stake-tx';
export const REMOVE_PENDING_STAKE_TX = '@cardano-staking/remove-pending-stake-tx';
export const IS_LOADING = '@cardano-staking/is-loading';
export const SET_TREZOR_POOLS = '@cardano-staking/set-trezor-pools';
export const SET_TREZOR_DATA = '@cardano-staking/set-trezor-data';
export const SET_FETCH_LOADING = '@cardano-staking/set-fetch-loading';
export const SET_FETCH_ERROR = '@cardano-staking/set-fetch-error';
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { Button, Icon, Link, NewModal, Row, Column, Text, Card } from '@trezor/components';
import { spacings } from '@trezor/theme';
import { getNetworkName } from '@suite-common/wallet-utils';

import { useSelector } from 'src/hooks/suite/useSelector';
import { useCardanoStaking } from 'src/hooks/wallet/useCardanoStaking';
import { Translation } from 'src/components/suite';
import { selectSelectedAccount } from 'src/reducers/wallet/selectedAccountReducer';

export const CardanoWithdrawModal = ({ onCancel }: { onCancel: () => void }) => {
const { voteAbstain, voteDelegate } = useCardanoStaking();
const account = useSelector(state => selectSelectedAccount(state));

if (!account || account.networkType !== 'cardano') {
throw Error(
'CardanoWithdrawModal used for other network or account in selectedAccount is undefined',
);
}

const cardanoNetwork = getNetworkName(account.symbol);
const { trezorDRep } = useSelector(state => state.wallet.cardanoStaking[cardanoNetwork]);
const trezorDRepBech32 = trezorDRep?.drep.bech32;

return (
<NewModal
onCancel={onCancel}
heading={<Translation id="TR_CARDANO_WITHDRAW_MODAL_TITLE" />}
description={<Translation id="TR_CARDANO_WITHDRAW_MODAL_TITLE_DESCRIPTION" />}
>
<Row padding={{ top: spacings.xl }}>
<Column>
<Row padding={{ bottom: spacings.md }}>
<Text>
<Translation id="TR_CARDANO_WITHDRAW_MODAL_SUB_TITLE" />
</Text>
</Row>
<Card>
<Row>
{trezorDRepBech32}
<Link href={`https://gov.tools/drep_directory/${trezorDRepBech32}`}>
<Row padding={{ left: spacings.sm }}>
<Icon name="link" size={16} />
</Row>
</Link>
</Row>
</Card>
</Column>
</Row>
<Row padding={{ top: spacings.xl }}>
<Button onClick={() => voteDelegate()}>
<Translation id="TR_CARDANO_WITHDRAW_MODAL_BUTTON_DELEGATE" />
</Button>
<Row padding={{ left: spacings.sm }}>
<Button onClick={() => voteAbstain()} variant="tertiary">
<Translation id="TR_CARDANO_WITHDRAW_MODAL_BUTTON_ABSTAIN" />
</Button>
</Row>
</Row>
</NewModal>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ import type { ReduxModalProps } from '../ReduxModal';
import { EverstakeModal } from './UnstakeModal/EverstakeModal';
import { PassphraseMismatchModal } from './PassphraseMismatchModal';
import { FirmwareRevisionOptOutModal } from './FirmwareRevisionOptOutModal';
import { CardanoWithdrawModal } from '../CardanoWithdrawModal';

/** Modals opened as a result of user action */
export const UserContextModal = ({
Expand Down Expand Up @@ -105,6 +106,8 @@ export const UserContextModal = ({
);
case 'review-transaction':
return <TransactionReviewModal {...payload} />;
case 'cardano-withdraw-modal':
return <CardanoWithdrawModal onCancel={onCancel} />;
case 'coinmarket-buy-terms': {
return (
<CoinmarketTermsModal
Expand Down
Loading

0 comments on commit 2a0724b

Please sign in to comment.