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

Cardano withdrawal modal with governance #10

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
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 @@ -239,6 +239,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 { Icon, Link, NewModal, Row, Column, Text, Card, Paragraph } 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" />}
bottomContent={
<>
<NewModal.Button onClick={() => voteDelegate()}>
<Translation id="TR_CARDANO_WITHDRAW_MODAL_BUTTON_DELEGATE" />
</NewModal.Button>
<NewModal.Button onClick={() => voteAbstain()} variant="tertiary">
<Translation id="TR_CARDANO_WITHDRAW_MODAL_BUTTON_ABSTAIN" />
</NewModal.Button>
</>
}
>
<Paragraph variant="tertiary">
<Translation id="TR_CARDANO_WITHDRAW_MODAL_TITLE_DESCRIPTION" />
</Paragraph>
<Row padding={{ top: spacings.xl }}>
<Column gap={spacings.md}>
<Text>
<Translation id="TR_CARDANO_WITHDRAW_MODAL_SUB_TITLE" />
</Text>
<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>
</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
Loading