Skip to content

Commit cccf840

Browse files
committed
feat(suite-native): enable and discover account via trade
1 parent ad2189b commit cccf840

31 files changed

+976
-619
lines changed

suite-native/intl/src/en.ts

+17-4
Original file line numberDiff line numberDiff line change
@@ -1293,10 +1293,23 @@ export const en = {
12931293
emptyDescription:
12941294
'We couldn’t find a country matching your search. Try checking the spelling or exploring the list for the right option.',
12951295
},
1296-
accountSheet: {
1297-
addressEmptyTitle: 'No address found',
1298-
addressEmptyDescription:
1299-
'We couldn’t find an address matching your search. Try checking the spelling or exploring the list for the right option.',
1296+
accountScreen: {
1297+
accountEmpty: {
1298+
viewOnly: {
1299+
title: 'No account found',
1300+
description: 'You need to connect your device to add new account.',
1301+
},
1302+
networkNotEnabled: {
1303+
title: 'No account found',
1304+
description:
1305+
"It seems that you don't have any account matching selected asset.",
1306+
},
1307+
},
1308+
addressEmpty: {
1309+
title: 'No address found',
1310+
description:
1311+
'We couldn’t find an address matching your search. Try checking the spelling or exploring the list for the right option.',
1312+
},
13001313
titleStep1: 'Pick account',
13011314
newAddress: 'New address',
13021315
usedAddresses: 'Used addresses',

suite-native/module-add-accounts/src/hooks/useAddCoinAccount.ts

+104-36
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@ import { useMemo, useState } from 'react';
22
import { useDispatch, useSelector } from 'react-redux';
33

44
import { A, pipe } from '@mobily/ts-belt';
5-
import { CommonActions, useNavigation } from '@react-navigation/native';
5+
import { CommonActions, useNavigation, useRoute } from '@react-navigation/native';
66
import { isRejected } from '@reduxjs/toolkit';
77

8+
import { UnreachableCaseError } from '@suite-common/suite-utils';
89
import {
910
type AccountType,
1011
NORMAL_ACCOUNT_TYPE,
@@ -49,8 +50,10 @@ export type AddCoinAccountNavigationProps = StackToStackCompositeNavigationProps
4950
RootStackParamList
5051
>;
5152

53+
export type AddCoinEnabledAccountType = Exclude<AccountType, 'coinjoin' | 'imported' | 'ledger'>;
54+
5255
export const accountTypeTranslationKeys: Record<
53-
Exclude<AccountType, 'coinjoin' | 'imported' | 'ledger'>,
56+
AddCoinEnabledAccountType,
5457
{ titleKey: TxKeyPath; subtitleKey: TxKeyPath; descKey: TxKeyPath }
5558
> = {
5659
normal: {
@@ -78,6 +81,7 @@ export const accountTypeTranslationKeys: Record<
7881
export const useAddCoinAccount = () => {
7982
const dispatch = useDispatch();
8083
const { translate } = useTranslate();
84+
const { name: routeName } = useRoute();
8185

8286
const supportedNetworkSymbols = useSelector(selectDiscoveryNetworkSymbols);
8387
const deviceAccounts = useSelector((state: AccountsRootState & DeviceRootState) =>
@@ -98,7 +102,7 @@ export const useAddCoinAccount = () => {
98102
} = useAddCoinAccountAlerts();
99103

100104
const [networkSymbolWithTypeToBeAdded, setNetworkSymbolWithTypeToBeAdded] = useState<
101-
[NetworkSymbol, AccountType] | null
105+
[NetworkSymbol, AddCoinEnabledAccountType] | null
102106
>(null);
103107

104108
const availableNetworkAccountTypes = useMemo(() => {
@@ -133,7 +137,11 @@ export const useAddCoinAccount = () => {
133137

134138
const setDefaultAccountToBeAdded = (symbol: NetworkSymbol) => {
135139
const defaultType = getAvailableAccountTypesForNetworkSymbol({ symbol })[0];
136-
setNetworkSymbolWithTypeToBeAdded([symbol, defaultType]);
140+
const type = defaultType as AddCoinEnabledAccountType;
141+
142+
if (type) {
143+
setNetworkSymbolWithTypeToBeAdded([symbol, type]);
144+
}
137145
};
138146

139147
const navigateToSuccessorScreen = ({
@@ -178,9 +186,64 @@ export const useAddCoinAccount = () => {
178186
},
179187
});
180188
break;
189+
case 'trade':
190+
if (
191+
routeName === AddCoinAccountStackRoutes.AddCoinDiscoveryFinished ||
192+
routeName === AddCoinAccountStackRoutes.SelectAccountType
193+
) {
194+
navigation.popToTop();
195+
}
196+
break;
197+
198+
default:
199+
throw new UnreachableCaseError(flowType);
181200
}
182201
};
183202

203+
const navigateToFailureScreen = ({
204+
flowType,
205+
errorString,
206+
}: {
207+
flowType: AddCoinFlowType;
208+
errorString: string | undefined;
209+
}) => {
210+
let screen: AppTabsRoutes;
211+
switch (flowType) {
212+
case 'home':
213+
case 'receive':
214+
screen = AppTabsRoutes.HomeStack;
215+
break;
216+
case 'accounts':
217+
screen = AppTabsRoutes.AccountsStack;
218+
break;
219+
case 'trade':
220+
screen = AppTabsRoutes.TradeStack;
221+
break;
222+
223+
default:
224+
throw new UnreachableCaseError(flowType);
225+
}
226+
227+
if (errorString === 'Passphrase is incorrect') {
228+
showPassphraseAuthAlert();
229+
} else {
230+
showGeneralErrorAlert();
231+
}
232+
navigation.dispatch(
233+
CommonActions.reset({
234+
index: 0,
235+
routes: [
236+
{
237+
name: RootStackRoutes.AppTabs,
238+
params: {
239+
screen,
240+
},
241+
},
242+
],
243+
}),
244+
);
245+
};
246+
184247
const clearNetworkWithTypeToBeAdded = () => {
185248
setNetworkSymbolWithTypeToBeAdded(null);
186249
};
@@ -211,13 +274,16 @@ export const useAddCoinAccount = () => {
211274
return true;
212275
};
213276

214-
const handleAccountTypeSelection = flowType => {
277+
const handleAccountTypeSelection = (flowType: AddCoinFlowType) => {
215278
if (networkSymbolWithTypeToBeAdded) {
216279
clearNetworkWithTypeToBeAdded();
217-
navigation.navigate(AddCoinAccountStackRoutes.SelectAccountType, {
218-
accountType: networkSymbolWithTypeToBeAdded[1] ?? NORMAL_ACCOUNT_TYPE,
219-
networkSymbol: networkSymbolWithTypeToBeAdded[0],
220-
flowType,
280+
navigation.navigate(RootStackRoutes.AddCoinAccountStack, {
281+
screen: AddCoinAccountStackRoutes.SelectAccountType,
282+
params: {
283+
accountType: networkSymbolWithTypeToBeAdded[1] ?? NORMAL_ACCOUNT_TYPE,
284+
networkSymbol: networkSymbolWithTypeToBeAdded[0],
285+
flowType,
286+
},
221287
});
222288
}
223289
};
@@ -281,29 +347,7 @@ export const useAddCoinAccount = () => {
281347
!firstHiddenEmptyAccount && // Do not show error if we are just making the first hidden empty account visible
282348
isRejected(newAccountResult)
283349
) {
284-
let screen = AppTabsRoutes.HomeStack;
285-
if (flowType === 'accounts') {
286-
screen = AppTabsRoutes.AccountsStack;
287-
}
288-
289-
if (newAccountResult.payload === 'Passphrase is incorrect') {
290-
showPassphraseAuthAlert();
291-
} else {
292-
showGeneralErrorAlert();
293-
}
294-
navigation.dispatch(
295-
CommonActions.reset({
296-
index: 0,
297-
routes: [
298-
{
299-
name: RootStackRoutes.AppTabs,
300-
params: {
301-
screen,
302-
},
303-
},
304-
],
305-
}),
306-
);
350+
navigateToFailureScreen({ flowType, errorString: newAccountResult.payload });
307351
}
308352
};
309353

@@ -322,10 +366,21 @@ export const useAddCoinAccount = () => {
322366

323367
if (!enabledDiscoveryNetworkSymbols.includes(symbol)) {
324368
clearNetworkWithTypeToBeAdded();
325-
navigation.replace(AddCoinAccountStackRoutes.AddCoinDiscoveryRunning, {
326-
networkSymbol: symbol,
327-
flowType,
328-
});
369+
370+
if (flowType === 'trade') {
371+
navigation.navigate(RootStackRoutes.AddCoinAccountStack, {
372+
screen: AddCoinAccountStackRoutes.AddCoinDiscoveryRunning,
373+
params: {
374+
networkSymbol: symbol,
375+
flowType,
376+
},
377+
});
378+
} else {
379+
navigation.replace(AddCoinAccountStackRoutes.AddCoinDiscoveryRunning, {
380+
networkSymbol: symbol,
381+
flowType,
382+
});
383+
}
329384

330385
return;
331386
}
@@ -339,6 +394,18 @@ export const useAddCoinAccount = () => {
339394
}
340395
};
341396

397+
const handleAccountTypeConfirmation = async (flowType: AddCoinFlowType) => {
398+
if (networkSymbolWithTypeToBeAdded) {
399+
clearNetworkWithTypeToBeAdded();
400+
await new Promise(resolve => setTimeout(resolve, 100));
401+
await addCoinAccount({
402+
symbol: networkSymbolWithTypeToBeAdded[0],
403+
accountType: networkSymbolWithTypeToBeAdded[1],
404+
flowType,
405+
});
406+
}
407+
};
408+
342409
return {
343410
supportedNetworkSymbols,
344411
onSelectedNetworkItem,
@@ -349,5 +416,6 @@ export const useAddCoinAccount = () => {
349416
clearNetworkWithTypeToBeAdded,
350417
getAccountTypeToBeAddedName,
351418
handleAccountTypeSelection,
419+
handleAccountTypeConfirmation,
352420
};
353421
};
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
11
export * from './navigation/AddCoinAccountStackNavigator';
2+
export * from './hooks/useAddCoinAccount';
3+
export * from './components/AccountTypeDecisionBottomSheet';

suite-native/module-add-accounts/src/screens/AddCoinAccountScreen.tsx

+2-14
Original file line numberDiff line numberDiff line change
@@ -25,27 +25,15 @@ export const AddCoinAccountScreen = ({
2525
networkSymbolWithTypeToBeAdded,
2626
clearNetworkWithTypeToBeAdded,
2727
handleAccountTypeSelection,
28-
addCoinAccount,
28+
handleAccountTypeConfirmation,
2929
getAccountTypeToBeAddedName,
3030
} = useAddCoinAccount();
3131

3232
const { flowType } = route.params;
3333

3434
const handleTypeSelectionTap = () => handleAccountTypeSelection(flowType);
3535

36-
const handleConfirmTap = () => {
37-
if (networkSymbolWithTypeToBeAdded) {
38-
// Timeout is needed so AccountTypeDecisionBottomSheet has time to hide otherwise app crashes
39-
setTimeout(() => {
40-
addCoinAccount({
41-
symbol: networkSymbolWithTypeToBeAdded[0],
42-
accountType: networkSymbolWithTypeToBeAdded[1],
43-
flowType,
44-
});
45-
}, 100);
46-
clearNetworkWithTypeToBeAdded();
47-
}
48-
};
36+
const handleConfirmTap = () => handleAccountTypeConfirmation(flowType);
4937

5038
return (
5139
<Screen

suite-native/module-add-accounts/src/screens/AddCoinDiscoveryFinishedScreen.tsx

+24-21
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,34 @@ import { Account } from '@suite-common/wallet-types';
1212
import { AccountsListItem } from '@suite-native/accounts';
1313
import { Box, Button, Card, Text, TextDivider } from '@suite-native/atoms';
1414
import { Translation } from '@suite-native/intl';
15-
import { Screen, ScreenHeader } from '@suite-native/navigation';
15+
import {
16+
AddCoinAccountStackParamList,
17+
AddCoinAccountStackRoutes,
18+
RootStackParamList,
19+
Screen,
20+
ScreenHeader,
21+
StackProps,
22+
StackToStackCompositeNavigationProps,
23+
} from '@suite-native/navigation';
1624
import { prepareNativeStyle, useNativeStyles } from '@trezor/styles';
1725

1826
import { AccountTypeDecisionBottomSheet } from '../components/AccountTypeDecisionBottomSheet';
1927
import { useAddCoinAccount } from '../hooks/useAddCoinAccount';
2028

29+
export type AddCoinDiscoveryFinishedScreenNavigationProps = StackToStackCompositeNavigationProps<
30+
AddCoinAccountStackParamList,
31+
AddCoinAccountStackRoutes.AddCoinDiscoveryFinished,
32+
RootStackParamList
33+
>;
34+
2135
const accountsStyle = prepareNativeStyle(_ => ({ paddingHorizontal: 0, paddingTop: 0 }));
2236

23-
export const AddCoinDiscoveryFinishedScreen = ({ route }) => {
37+
export const AddCoinDiscoveryFinishedScreen = ({
38+
route,
39+
}: StackProps<
40+
AddCoinAccountStackParamList,
41+
AddCoinAccountStackRoutes.AddCoinDiscoveryFinished
42+
>) => {
2443
const { networkSymbol, flowType } = route.params;
2544

2645
const { applyStyle } = useNativeStyles();
@@ -29,7 +48,7 @@ export const AddCoinDiscoveryFinishedScreen = ({ route }) => {
2948
).filter(a => !a.empty);
3049
const {
3150
navigateToSuccessorScreen,
32-
addCoinAccount,
51+
handleAccountTypeConfirmation,
3352
onSelectedNetworkItem,
3453
networkSymbolWithTypeToBeAdded,
3554
clearNetworkWithTypeToBeAdded,
@@ -49,19 +68,7 @@ export const AddCoinDiscoveryFinishedScreen = ({ route }) => {
4968

5069
const handleTypeSelectionTap = () => handleAccountTypeSelection(flowType);
5170

52-
const handleConfirmTap = () => {
53-
if (networkSymbolWithTypeToBeAdded) {
54-
// Timeout is needed so AccountTypeDecisionBottomSheet has time to hide otherwise app crashes
55-
setTimeout(() => {
56-
addCoinAccount({
57-
symbol: networkSymbolWithTypeToBeAdded[0],
58-
accountType: networkSymbolWithTypeToBeAdded[1],
59-
flowType,
60-
});
61-
}, 100);
62-
clearNetworkWithTypeToBeAdded();
63-
}
64-
};
71+
const handleConfirmTap = () => handleAccountTypeConfirmation(flowType);
6572

6673
const titleKey =
6774
accounts.length === 1
@@ -105,11 +112,7 @@ export const AddCoinDiscoveryFinishedScreen = ({ route }) => {
105112
</Box>
106113
</Card>
107114
<AccountTypeDecisionBottomSheet
108-
coinName={
109-
G.isNotNullable(networkSymbolWithTypeToBeAdded)
110-
? networkSymbolWithTypeToBeAdded[0]
111-
: ''
112-
}
115+
coinName={networkSymbol}
113116
typeName={getAccountTypeToBeAddedName()}
114117
isVisible={G.isNotNullable(networkSymbolWithTypeToBeAdded)}
115118
onClose={clearNetworkWithTypeToBeAdded}

0 commit comments

Comments
 (0)