Skip to content

Commit

Permalink
feat(suite-native): send solana
Browse files Browse the repository at this point in the history
  • Loading branch information
vytick committed Nov 26, 2024
1 parent e22b7b2 commit e603734
Show file tree
Hide file tree
Showing 7 changed files with 64 additions and 18 deletions.
5 changes: 4 additions & 1 deletion suite-native/intl/src/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1051,8 +1051,10 @@ export const en = {
description: 'Reconnect your Trezor to continue.',
primaryButton: 'Reconnect Trezor',
},
lockedToast: 'Device is locked.',
destinationTagTitle: 'Check & confirm XRP destination tag on your Trezor.',
toasts: {
sendTxnFailed: 'Failed to send transaction',
},
address: {
title: 'Check the address on your Trezor against the original to make sure it’s correct.',
step1: 'Go to the app or place where you originally got the address.',
Expand Down Expand Up @@ -1087,6 +1089,7 @@ export const en = {
addressLabel: 'Recipient address',
amountLabel: 'Amount',
destinationTagLabel: 'Destination tag',
contractLabel: 'Token address',
summary: {
label: 'Total including fee',
totalAmount: 'Total amount',
Expand Down
12 changes: 11 additions & 1 deletion suite-native/module-send/src/components/CustomFee.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,18 @@ import { Box, Button } from '@suite-native/atoms';
import { Icon } from '@suite-native/icons';
import { Translation } from '@suite-native/intl';
import { useFormContext } from '@suite-native/forms';
import { getNetworkType, NetworkSymbol } from '@suite-common/wallet-config';

import { CustomFeeBottomSheet } from './CustomFeeBottomSheet';
import { SendFeesFormValues } from '../sendFeesFormSchema';
import { CustomFeeCard } from './CustomFeeCard';
import { NativeSupportedFeeLevel } from '../types';

export const CustomFee = () => {
type CustomFeeProps = {
networkSymbol: NetworkSymbol;
};

export const CustomFee = ({ networkSymbol }: CustomFeeProps) => {
const [isBottomSheetVisible, setIsBottomSheetVisible] = useState(false);
const [previousSelectedFeeLevelLabel, setPreviousSelectedFeeLevelLabel] =
useState<NativeSupportedFeeLevel>('normal');
Expand All @@ -36,6 +41,11 @@ export const CustomFee = () => {
setIsBottomSheetVisible(false);
};

// custom fees are not allowed for solana
if (getNetworkType(networkSymbol) === 'solana') {
return null;
}

return (
<Box flex={1}>
{isCustomFeeSelected ? (
Expand Down
45 changes: 38 additions & 7 deletions suite-native/module-send/src/components/OutputsReviewFooter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import Animated, { SlideInDown } from 'react-native-reanimated';

import { useAtomValue } from 'jotai';
import { CommonActions, useNavigation } from '@react-navigation/native';
import { isFulfilled } from '@reduxjs/toolkit';
import { G } from '@mobily/ts-belt';
import { isFulfilled } from '@reduxjs/toolkit';

import {
AccountsRootState,
Expand All @@ -18,23 +18,37 @@ import {
} from '@suite-common/wallet-core';
import { AccountKey, TokenAddress } from '@suite-common/wallet-types';
import { Button } from '@suite-native/atoms';
import { RootStackRoutes, AppTabsRoutes, RootStackParamList } from '@suite-native/navigation';
import {
RootStackRoutes,
AppTabsRoutes,
RootStackParamList,
SendStackRoutes,
SendStackParamList,
StackToStackCompositeNavigationProps,
} from '@suite-native/navigation';
import { Translation } from '@suite-native/intl';
import { prepareNativeStyle, useNativeStyles } from '@trezor/styles';
import { analytics, EventType } from '@suite-native/analytics';
import { selectAccountTokenSymbol, TokensRootState } from '@suite-native/tokens';
import { useAlert } from '@suite-native/alerts';

import { SendConfirmOnDeviceImage } from '../components/SendConfirmOnDeviceImage';
import { cleanupSendFormThunk } from '../sendFormThunks';
import { wasAppLeftDuringReviewAtom } from '../atoms/wasAppLeftDuringReviewAtom';
import { selectIsTransactionAlreadySigned } from '../selectors';

const navigateToAccountDetail = ({
type NavigationProps = StackToStackCompositeNavigationProps<
SendStackParamList,
SendStackRoutes.SendOutputsReview,
RootStackParamList
>;

const navigateToTransactionDetail = ({
accountKey,
tokenContract,
txid,
}: RootStackParamList[RootStackRoutes.TransactionDetail]) =>
// Reset navigation stack to the account detail screen with HomeStack as a previous step, so the user can navigate back there.
// Reset navigation stack to the transaction detail screen with HomeStack as a previous step, so the user can navigate back there.
CommonActions.reset({
index: 1,
routes: [
Expand Down Expand Up @@ -77,8 +91,9 @@ export const OutputsReviewFooter = ({
}) => {
const [txid, setTxid] = useState<string>('');
const dispatch = useDispatch();
const navigation = useNavigation();
const navigation = useNavigation<NavigationProps>();
const { applyStyle } = useNativeStyles();
const { showAlert } = useAlert();
const [isSendInProgress, setIsSendInProgress] = useState(false);
const wasAppLeftDuringReview = useAtomValue(wasAppLeftDuringReviewAtom);

Expand All @@ -104,7 +119,7 @@ export const OutputsReviewFooter = ({
// Navigate to transaction detail screen only at the moment when the transaction was already processed by backend and we have all its data.
if (isTransactionProcessedByBackend) {
navigation.dispatch(
navigateToAccountDetail({
navigateToTransactionDetail({
accountKey,
tokenContract,
txid,
Expand All @@ -127,7 +142,6 @@ export const OutputsReviewFooter = ({
shouldDiscardTransaction: false,
}),
);

if (isFulfilled(sendResponse)) {
const { txid: sentTxid } = sendResponse.payload.payload;

Expand All @@ -147,7 +161,24 @@ export const OutputsReviewFooter = ({
}

setTxid(sentTxid);

return;
}
showAlert({
icon: 'warningCircle',
title: <Translation id="moduleSend.review.toasts.sendTxnFailed" />,
description: sendResponse.payload?.metadata.payload.error ?? sendResponse.error.message,
primaryButtonTitle: <Translation id="generic.buttons.close" />,
primaryButtonVariant: 'redBold',
onPressPrimaryButton: () => {
dispatch(cleanupSendFormThunk({ accountKey, shouldDeleteDraft: true }));
navigation.navigate(SendStackRoutes.SendOutputs, {
accountKey,
tokenContract,
});
},
});
setIsSendInProgress(false);
};

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const outputLabelTranslationMap = {
regular_legacy: 'moduleSend.review.outputs.addressLabel',
amount: 'moduleSend.review.outputs.amountLabel',
'destination-tag': 'moduleSend.review.outputs.destinationTagLabel',
contract: 'moduleSend.review.outputs.contractLabel',
} as const satisfies Partial<Record<ReviewOutputType, TxKeyPath>>;

const isTranslationDefined = (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export const ReviewOutputItemContent = ({
return <Text variant="hint">{value}</Text>;
}

if (outputType === 'address' || outputType === 'regular_legacy') {
if (outputType === 'address' || outputType === 'regular_legacy' || outputType === 'contract') {
const chunkedAddress = splitAddressToChunks(value).join(' ');

return <Text variant="hint">{chunkedAddress}</Text>;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { useSelector } from 'react-redux';
import { LayoutChangeEvent, View } from 'react-native';

import { getNetworkType, NetworkSymbol } from '@suite-common/wallet-config';
import { NetworkSymbol } from '@suite-common/wallet-config';
import { AccountsRootState, DeviceRootState, SendRootState } from '@suite-common/wallet-core';
import { AccountKey, TokenAddress } from '@suite-common/wallet-types';
import { VStack } from '@suite-native/atoms';
import { useTranslate } from '@suite-native/intl';
import { BigNumber } from '@trezor/utils';
import { isCoinWithTokens } from '@suite-native/tokens';

import { selectReviewSummaryOutput } from '../selectors';
import { ReviewOutputItemValues } from './ReviewOutputItemValues';
Expand All @@ -19,14 +20,14 @@ type ReviewOutputSummaryItemProps = {
tokenContract?: TokenAddress;
};

type EthereumValuesProps = {
type ValuesProps = {
totalSpent: string;
fee: string;
networkSymbol: NetworkSymbol;
tokenContract?: TokenAddress;
};

const BitcoinValues = ({ totalSpent, fee, networkSymbol }: EthereumValuesProps) => {
const BitcoinValues = ({ totalSpent, fee, networkSymbol }: ValuesProps) => {
return (
<>
<ReviewOutputItemValues
Expand All @@ -43,7 +44,7 @@ const BitcoinValues = ({ totalSpent, fee, networkSymbol }: EthereumValuesProps)
);
};

const EthereumValues = ({ totalSpent, fee, tokenContract, networkSymbol }: EthereumValuesProps) => {
const TokenEnabledValues = ({ totalSpent, fee, tokenContract, networkSymbol }: ValuesProps) => {
const amount = tokenContract ? totalSpent : BigNumber(totalSpent).minus(fee).toString();

return (
Expand Down Expand Up @@ -79,7 +80,7 @@ export const ReviewOutputSummaryItem = ({

const { state, totalSpent, fee } = summaryOutput;

const isEthereumBasedNetwork = getNetworkType(networkSymbol) === 'ethereum';
const canHaveTokens = isCoinWithTokens(networkSymbol);

return (
<View onLayout={onLayout}>
Expand All @@ -88,8 +89,8 @@ export const ReviewOutputSummaryItem = ({
outputState={state}
>
<VStack spacing="sp16">
{isEthereumBasedNetwork ? (
<EthereumValues
{canHaveTokens ? (
<TokenEnabledValues
totalSpent={totalSpent}
fee={fee}
networkSymbol={networkSymbol}
Expand Down
2 changes: 1 addition & 1 deletion suite-native/module-send/src/components/SendFeesForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ export const SendFeesForm = ({ accountKey, tokenContract }: SendFormProps) => {
tokenContract={tokenContract}
/>
)}
<CustomFee />
<CustomFee networkSymbol={account.symbol} />
</VStack>
</VStack>
<FeesFooter
Expand Down

0 comments on commit e603734

Please sign in to comment.