diff --git a/src/const/navigation.js b/src/const/navigation.js
index 03a7dc51af..b317a0a289 100644
--- a/src/const/navigation.js
+++ b/src/const/navigation.js
@@ -130,8 +130,6 @@ export const ScreenName = {
SignSummary: "SignSummary",
SignValidationError: "SignValidationError",
SignValidationSuccess: "SignValidationSuccess",
- StellarEditMemoType: "StellarEditMemoType",
- StellarEditMemoValue: "StellarEditMemoValue",
Swap: "Swap",
SwapError: "SwapError",
SwapFormOrHistory: "SwapFormOrHistory",
@@ -243,6 +241,17 @@ export const ScreenName = {
PolkadotSimpleOperationValidationSuccess:
"PolkadotSimpleOperationValidationSuccess",
+ // Stellar
+ StellarEditMemoType: "StellarEditMemoType",
+ StellarEditMemoValue: "StellarEditMemoValue",
+ StellarEditCustomFees: "StellarEditCustomFees",
+ StellarAddAssetSelectAsset: "StellarAddAssetSelectAsset",
+ StellarAddAssetSelectDevice: "StellarAddAssetSelectDevice",
+ StellarAddAssetConnectDevice: "StellarAddAssetConnectDevice",
+ StellarAddAssetValidation: "StellarAddAssetValidation",
+ StellarAddAssetValidationError: "StellarAddAssetValidationError",
+ StellarAddAssetValidationSuccess: "StellarAddAssetValidationSuccess",
+
LendingDashboard: "LendingDashboard",
LendingClosedLoans: "LendingClosedLoans",
LendingHistory: "LendingHistory",
@@ -413,6 +422,9 @@ export const NavigatorName = {
PolkadotNominateFlow: "PolkadotNominateFlow",
PolkadotSimpleOperationFlow: "PolkadotSimpleOperationFlow",
+ // Stellar
+ StellarAddAssetFlow: "StellarAddAssetFlow",
+
NotificationCenter: "NotificationCenter",
Market: "Market",
diff --git a/src/families/stellar/AddAssetFlow/01-SelectAsset.js b/src/families/stellar/AddAssetFlow/01-SelectAsset.js
new file mode 100644
index 0000000000..bca1e5efd2
--- /dev/null
+++ b/src/families/stellar/AddAssetFlow/01-SelectAsset.js
@@ -0,0 +1,274 @@
+// @flow
+import invariant from "invariant";
+import React, { useCallback, useState } from "react";
+import {
+ View,
+ StyleSheet,
+ SafeAreaView,
+ FlatList,
+ TouchableOpacity,
+} from "react-native";
+import { Trans, useTranslation } from "react-i18next";
+import { useSelector } from "react-redux";
+
+import { getMainAccount } from "@ledgerhq/live-common/lib/account/helpers";
+import { getAccountBridge } from "@ledgerhq/live-common/lib/bridge/impl";
+import useBridgeTransaction from "@ledgerhq/live-common/lib/bridge/useBridgeTransaction";
+import { listTokensForCryptoCurrency } from "@ledgerhq/live-common/lib/currencies";
+
+import type {
+ TokenCurrency,
+ SubAccount,
+} from "@ledgerhq/live-common/lib/types";
+
+import { useTheme } from "@react-navigation/native";
+import { ScreenName } from "../../../const";
+import LText from "../../../components/LText";
+import { accountScreenSelector } from "../../../reducers/accounts";
+import { TrackScreen } from "../../../analytics";
+import FilteredSearchBar from "../../../components/FilteredSearchBar";
+import FirstLetterIcon from "../../../components/FirstLetterIcon";
+import KeyboardView from "../../../components/KeyboardView";
+import InfoIcon from "../../../components/InfoIcon";
+import Info from "../../../icons/Info";
+import BottomModal from "../../../components/BottomModal";
+
+const Row = ({
+ item,
+ onPress,
+ onDisabledPress,
+ disabled,
+}: {
+ item: TokenCurrency,
+ onPress: () => void,
+ onDisabledPress: () => void,
+ disabled: boolean,
+}) => {
+ const { colors } = useTheme();
+ const tokenId = item.id.split("/")[2];
+ const assetIssuer = tokenId.split(":")[1];
+ return (
+
+
+
+ {item.name}
+
+
+ -
+
+
+ {assetIssuer}
+
+
+ );
+};
+
+const keyExtractor = token => token.id;
+
+const renderEmptyList = () => (
+
+
+
+
+
+);
+
+type RouteParams = {
+ accountId: string,
+};
+
+type Props = {
+ navigation: any,
+ route: { params: RouteParams },
+};
+
+export default function DelegationStarted({ navigation, route }: Props) {
+ const { colors } = useTheme();
+ const { account } = useSelector(accountScreenSelector(route));
+ const { t } = useTranslation();
+
+ invariant(account, "Account required");
+
+ const mainAccount = getMainAccount(account);
+ const bridge = getAccountBridge(mainAccount);
+
+ invariant(mainAccount, "stellar Account required");
+
+ const { transaction } = useBridgeTransaction(() => {
+ const t = bridge.createTransaction(mainAccount);
+
+ return {
+ account,
+ transaction: bridge.updateTransaction(t, {
+ operationType: "changeTrust",
+ }),
+ };
+ });
+
+ const onNext = useCallback(
+ (assetId: string) => {
+ const tokenId = assetId.split("/")[2];
+ const [assetCode, assetIssuer] = tokenId.split(":");
+
+ navigation.navigate(ScreenName.StellarAddAssetSelectDevice, {
+ ...route.params,
+ transaction: bridge.updateTransaction(transaction, {
+ assetCode,
+ assetIssuer,
+ }),
+ });
+ },
+ [navigation, route.params, bridge, transaction],
+ );
+
+ const subAccounts = mainAccount.subAccounts || [];
+ const options = listTokensForCryptoCurrency(mainAccount.currency);
+
+ const [infoModalOpen, setInfoModalOpen] = useState(false);
+
+ const openModal = useCallback(token => setInfoModalOpen(token), [
+ setInfoModalOpen,
+ ]);
+ const closeModal = useCallback(() => setInfoModalOpen(false), [
+ setInfoModalOpen,
+ ]);
+
+ const renderList = useCallback(
+ list => (
+ (
+
+ sub.type === "TokenAccount" &&
+ sub.token &&
+ sub.token.id === item.id,
+ )}
+ onPress={() => onNext(item.id)}
+ onDisabledPress={() => openModal(item.name)}
+ />
+ )}
+ keyExtractor={keyExtractor}
+ />
+ ),
+ [subAccounts, onNext, openModal],
+ );
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ root: {
+ flex: 1,
+ },
+ keyboardView: { flex: 1 },
+ searchContainer: {
+ paddingTop: 16,
+ flex: 1,
+ },
+ filteredSearchInputWrapperStyle: {
+ marginHorizontal: 16,
+ },
+ row: {
+ flexDirection: "row",
+ alignItems: "center",
+ padding: 16,
+ },
+ name: {
+ marginLeft: 10,
+ fontSize: 14,
+ },
+ ticker: {
+ marginHorizontal: 5,
+ fontSize: 12,
+ },
+ assetId: {
+ fontSize: 12,
+ flex: 1,
+ },
+ emptySearch: {
+ paddingHorizontal: 16,
+ },
+ emptySearchText: {
+ textAlign: "center",
+ },
+ infoIcon: {
+ width: 80,
+ marginVertical: 16,
+ },
+ title: {
+ lineHeight: 24,
+ fontSize: 16,
+ },
+ warnText: {
+ textAlign: "center",
+ fontSize: 14,
+ lineHeight: 16,
+ marginVertical: 8,
+ },
+ infoRow: {
+ paddingHorizontal: 16,
+ flexDirection: "column",
+ alignItems: "center",
+ justifyContent: "center",
+ },
+ modal: {
+ flexDirection: "column",
+ alignItems: "center",
+ justifyContent: "center",
+ },
+});
diff --git a/src/families/stellar/AddAssetFlow/02-ConnectDevice.js b/src/families/stellar/AddAssetFlow/02-ConnectDevice.js
new file mode 100644
index 0000000000..0b63aa0fdb
--- /dev/null
+++ b/src/families/stellar/AddAssetFlow/02-ConnectDevice.js
@@ -0,0 +1,85 @@
+// @flow
+import invariant from "invariant";
+import React, { useCallback } from "react";
+import { StyleSheet, ScrollView, SafeAreaView } from "react-native";
+import { useSelector } from "react-redux";
+import type { Transaction } from "@ledgerhq/live-common/lib/types";
+import useBridgeTransaction from "@ledgerhq/live-common/lib/bridge/useBridgeTransaction";
+import { getMainAccount } from "@ledgerhq/live-common/lib/account";
+import { useTheme } from "@react-navigation/native";
+import { accountScreenSelector } from "../../../reducers/accounts";
+import { ScreenName } from "../../../const";
+import { TrackScreen } from "../../../analytics";
+import SelectDevice from "../../../components/SelectDevice";
+import {
+ connectingStep,
+ accountApp,
+} from "../../../components/DeviceJob/steps";
+
+type RouteParams = {
+ accountId: string,
+ transaction: Transaction,
+};
+
+type Props = {
+ navigation: any,
+ route: { params: RouteParams },
+};
+
+export default function ConnectDevice({ navigation, route }: Props) {
+ const { colors } = useTheme();
+ const { account } = useSelector(accountScreenSelector(route));
+
+ invariant(
+ account,
+ "account is required",
+ );
+
+ const mainAccount = getMainAccount(account, undefined);
+
+ const { transaction, status } = useBridgeTransaction(() => {
+ const transaction = route.params.transaction;
+ return { account, transaction };
+ });
+
+ const onSelectDevice = useCallback(
+ (meta: any) => {
+ navigation.replace(ScreenName.StellarAddAssetValidation, {
+ ...route.params,
+ ...meta,
+ transaction,
+ status,
+ });
+ },
+ [navigation, status, transaction, route.params],
+ );
+
+ if (!account) return null;
+
+ return (
+
+
+
+
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ root: {
+ flex: 1,
+ },
+ scroll: {
+ flex: 1,
+ },
+ scrollContainer: {
+ padding: 16,
+ },
+});
diff --git a/src/families/stellar/AddAssetFlow/03-Validation.js b/src/families/stellar/AddAssetFlow/03-Validation.js
new file mode 100644
index 0000000000..c0a1954288
--- /dev/null
+++ b/src/families/stellar/AddAssetFlow/03-Validation.js
@@ -0,0 +1,107 @@
+/* @flow */
+import React, { useMemo } from "react";
+import { View, StyleSheet, ActivityIndicator } from "react-native";
+import { useDispatch, useSelector } from "react-redux";
+import SafeAreaView from "react-native-safe-area-view";
+import invariant from "invariant";
+import type {
+ Transaction,
+ TransactionStatus,
+} from "@ledgerhq/live-common/lib/types";
+import type { DeviceModelId } from "@ledgerhq/devices";
+import { useTheme } from "@react-navigation/native";
+import { useSignWithDevice } from "../../../logic/screenTransactionHooks";
+import { updateAccountWithUpdater } from "../../../actions/accounts";
+import { accountScreenSelector } from "../../../reducers/accounts";
+import { TrackScreen } from "../../../analytics";
+import PreventNativeBack from "../../../components/PreventNativeBack";
+import ValidateOnDevice from "../../../components/ValidateOnDevice";
+import SkipLock from "../../../components/behaviour/SkipLock";
+
+const forceInset = { bottom: "always" };
+
+type RouteParams = {
+ accountId: string,
+ deviceId: string,
+ modelId: DeviceModelId,
+ wired: boolean,
+ transaction: Transaction,
+ status: TransactionStatus,
+};
+
+type Props = {
+ navigation: any,
+ route: { params: RouteParams },
+};
+
+export default function Validation({ navigation, route }: Props) {
+ const { colors } = useTheme();
+ const { account } = useSelector(accountScreenSelector(route));
+ invariant(account, "account is required");
+ const dispatch = useDispatch();
+
+ const [signing, signed] = useSignWithDevice({
+ context: "StellarAddAsset",
+ account,
+ parentAccount: undefined,
+ navigation,
+ updateAccountWithUpdater: (...args) =>
+ dispatch(updateAccountWithUpdater(...args)),
+ });
+
+ const { status, transaction, modelId, wired, deviceId } = route.params;
+
+ const device = useMemo(
+ () => ({
+ deviceId,
+ modelId,
+ wired,
+ }),
+ [modelId, wired, deviceId],
+ );
+
+ return (
+
+
+ {signing && (
+ <>
+
+
+ >
+ )}
+
+ {signed ? (
+
+
+
+ ) : (
+
+ )}
+
+ );
+}
+
+const styles = StyleSheet.create({
+ root: {
+ flex: 1,
+ },
+ center: {
+ flex: 1,
+ flexDirection: "column",
+ alignItems: "center",
+ justifyContent: "center",
+ },
+});
diff --git a/src/families/stellar/AddAssetFlow/03-ValidationError.js b/src/families/stellar/AddAssetFlow/03-ValidationError.js
new file mode 100644
index 0000000000..5e2cd6ea40
--- /dev/null
+++ b/src/families/stellar/AddAssetFlow/03-ValidationError.js
@@ -0,0 +1,60 @@
+/* @flow */
+import React, { useCallback } from "react";
+import { StyleSheet, Linking } from "react-native";
+import SafeAreaView from "react-native-safe-area-view";
+import { useTheme } from "@react-navigation/native";
+import { TrackScreen } from "../../../analytics";
+import ValidateError from "../../../components/ValidateError";
+import { urls } from "../../../config/urls";
+
+const forceInset = { bottom: "always" };
+
+type RouteParams = {
+ accountId: string,
+ deviceId: string,
+ transaction: any,
+ error: Error,
+};
+
+type Props = {
+ navigation: any,
+ route: { params: RouteParams },
+};
+
+export default function ValidationError({ navigation, route }: Props) {
+ const { colors } = useTheme();
+ const onClose = useCallback(() => {
+ navigation.getParent().pop();
+ }, [navigation]);
+
+ const contactUs = useCallback(() => {
+ Linking.openURL(urls.contact);
+ }, []);
+
+ const retry = useCallback(() => {
+ navigation.goBack();
+ }, [navigation]);
+
+ const error = route.params.error;
+
+ return (
+
+
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ root: {
+ flex: 1,
+ },
+});
diff --git a/src/families/stellar/AddAssetFlow/03-ValidationSuccess.js b/src/families/stellar/AddAssetFlow/03-ValidationSuccess.js
new file mode 100644
index 0000000000..0397eef687
--- /dev/null
+++ b/src/families/stellar/AddAssetFlow/03-ValidationSuccess.js
@@ -0,0 +1,84 @@
+/* @flow */
+import React, { useCallback, useMemo } from "react";
+import { View, StyleSheet } from "react-native";
+import { useSelector } from "react-redux";
+import { Trans } from "react-i18next";
+import type { Operation } from "@ledgerhq/live-common/lib/types";
+import { listTokensForCryptoCurrency } from "@ledgerhq/live-common/lib/currencies";
+import { useTheme } from "@react-navigation/native";
+import { accountScreenSelector } from "../../../reducers/accounts";
+import { TrackScreen } from "../../../analytics";
+import { ScreenName } from "../../../const";
+import PreventNativeBack from "../../../components/PreventNativeBack";
+import ValidateSuccess from "../../../components/ValidateSuccess";
+
+type Props = {
+ navigation: any,
+ route: { params: RouteParams },
+};
+
+type RouteParams = {
+ accountId: string,
+ deviceId: string,
+ transaction: any,
+ result: Operation,
+};
+
+export default function ValidationSuccess({ navigation, route }: Props) {
+ const { colors } = useTheme();
+ const { account } = useSelector(accountScreenSelector(route));
+ const { transaction } = route.params;
+
+ const onClose = useCallback(() => {
+ navigation.getParent().pop();
+ }, [navigation]);
+
+ const goToOperationDetails = useCallback(() => {
+ if (!account) return;
+
+ const result = route.params?.result;
+ if (!result) return;
+
+ navigation.navigate(ScreenName.OperationDetails, {
+ accountId: account.id,
+ operation: result,
+ });
+ }, [account, route.params, navigation]);
+
+ const token = useMemo(() => {
+ const options =
+ account && account.type === "Account"
+ ? listTokensForCryptoCurrency(account.currency)
+ : [];
+ return options.find(({ id }) => id === transaction.assetId);
+ }, [account, transaction]);
+
+ return (
+
+
+
+
+ }
+ description={
+
+ }
+ />
+
+ );
+}
+
+const styles = StyleSheet.create({
+ root: {
+ flex: 1,
+ },
+});
diff --git a/src/families/stellar/AddAssetFlow/index.js b/src/families/stellar/AddAssetFlow/index.js
new file mode 100644
index 0000000000..c98fe67323
--- /dev/null
+++ b/src/families/stellar/AddAssetFlow/index.js
@@ -0,0 +1,132 @@
+// @flow
+import React, { useMemo } from "react";
+import { Platform } from "react-native";
+import { useTranslation } from "react-i18next";
+import { createStackNavigator } from "@react-navigation/stack";
+import { useTheme } from "@react-navigation/native";
+import {
+ getStackNavigatorConfig,
+ defaultNavigationOptions,
+} from "../../../navigation/navigatorConfig";
+import StepHeader from "../../../components/StepHeader";
+import { ScreenName } from "../../../const";
+import SelectAsset from "./01-SelectAsset";
+import SelectDevice from "../../../screens/SelectDevice";
+import ConnectDevice from "../../../screens/ConnectDevice";
+import Validation from "./03-Validation";
+import ValidationError from "./03-ValidationError";
+import ValidationSuccess from "./03-ValidationSuccess";
+
+function AddAssetFlow() {
+ const { t } = useTranslation();
+ const { colors } = useTheme();
+ const stackNavigationConfig = useMemo(
+ () => getStackNavigatorConfig(colors, true),
+ [colors],
+ );
+
+ return (
+
+ (
+
+ ),
+ headerLeft: () => null,
+ headerStyle: {
+ ...defaultNavigationOptions.headerStyle,
+ elevation: 0,
+ shadowOpacity: 0,
+ borderBottomWidth: 0,
+ },
+ gestureEnabled: false,
+ }}
+ />
+ (
+
+ ),
+ }}
+ />
+ (
+
+ ),
+ }}
+ />
+ (
+
+ ),
+ headerLeft: null,
+ headerRight: null,
+ gestureEnabled: false,
+ }}
+ />
+
+
+
+ );
+}
+
+const options = {
+ headerShown: false,
+};
+
+export { AddAssetFlow as component, options };
+
+const Stack = createStackNavigator();
diff --git a/src/families/stellar/ScreenEditCustomFees.js b/src/families/stellar/ScreenEditCustomFees.js
new file mode 100644
index 0000000000..0bbf237d91
--- /dev/null
+++ b/src/families/stellar/ScreenEditCustomFees.js
@@ -0,0 +1,186 @@
+/* @flow */
+import { BigNumber } from "bignumber.js";
+import invariant from "invariant";
+import React, { useState, useCallback } from "react";
+import { useTranslation, Trans } from "react-i18next";
+import {
+ Keyboard,
+ StyleSheet,
+ View,
+ SafeAreaView,
+ ScrollView,
+} from "react-native";
+import { useTheme } from "@react-navigation/native";
+import { getAccountBridge } from "@ledgerhq/live-common/lib/bridge";
+import { getMainAccount } from "@ledgerhq/live-common/lib/account";
+import { useSelector } from "react-redux";
+import type { Transaction } from "@ledgerhq/live-common/lib/families/stellar/types";
+import Button from "../../components/Button";
+import KeyboardView from "../../components/KeyboardView";
+import LText from "../../components/LText";
+import { accountScreenSelector } from "../../reducers/accounts";
+import CurrencyInput from "../../components/CurrencyInput";
+
+const options = {
+ title: ,
+ headerLeft: null,
+};
+
+const forceInset = { bottom: "always" };
+
+type RouteParams = {
+ accountId: string,
+ transaction: Transaction,
+ currentNavigation: string,
+};
+
+type Props = {
+ navigation: any,
+ route: { params: RouteParams },
+};
+
+function StellarEditCustomFees({ navigation, route }: Props) {
+ const { colors } = useTheme();
+ const { t } = useTranslation();
+ const { transaction } = route.params;
+ const { account, parentAccount } = useSelector(accountScreenSelector(route));
+ invariant(transaction.family === "stellar", "not stellar family");
+ invariant(account, "no account found");
+
+ const mainAccount = getMainAccount(account, parentAccount);
+ const { networkCongestionLevel } = transaction?.networkInfo || {};
+ const [customFee, setCustomFee] = useState(transaction.fees);
+
+ const onChange = fee => {
+ setCustomFee(fee);
+ };
+
+ const onSubmit = useCallback(() => {
+ Keyboard.dismiss();
+
+ setCustomFee(BigNumber(customFee || 0));
+ const bridge = getAccountBridge(account, parentAccount);
+ const { currentNavigation } = route.params;
+
+ navigation.navigate(currentNavigation, {
+ ...route.params,
+ accountId: account.id,
+ transaction: bridge.updateTransaction(transaction, {
+ fees: BigNumber(customFee || 0),
+ }),
+ });
+ }, [
+ customFee,
+ account,
+ parentAccount,
+ route.params,
+ navigation,
+ transaction,
+ ]);
+
+ return (
+
+
+
+
+
+
+ {mainAccount.unit.code}
+
+ }
+ />
+
+
+
+ {networkCongestionLevel ? (
+
+
+ {`${t(
+ `stellar.networkCongestionLevel.${networkCongestionLevel}`,
+ )} ${t("stellar.networkCongestion")}`}
+
+
+ ) : null}
+
+
+
+
+
+
+
+ );
+}
+
+export { options, StellarEditCustomFees as component };
+
+const styles = StyleSheet.create({
+ root: {
+ flex: 1,
+ },
+ inputBox: {
+ flexDirection: "row",
+ alignItems: "flex-start",
+ padding: 20,
+ },
+ body: {
+ flexDirection: "column",
+ flex: 1,
+ },
+ textInputAS: {
+ fontSize: 30,
+ },
+ currency: {
+ fontSize: 20,
+ padding: 6,
+ },
+ buttonContainer: {
+ marginHorizontal: 16,
+ },
+ bottomButton: {
+ flex: 1,
+ flexDirection: "column",
+ justifyContent: "flex-end",
+ paddingBottom: 16,
+ },
+ feeWrapper: {
+ flex: 1,
+ flexBasis: 100,
+ flexShrink: 0,
+ flexDirection: "column",
+ justifyContent: "center",
+ },
+ congestionNote: {
+ flex: 1,
+ paddingHorizontal: 20,
+ paddingBottom: 20,
+ },
+ congestionNoteText: {
+ fontSize: 14,
+ },
+ active: {
+ fontSize: 32,
+ },
+});
diff --git a/src/families/stellar/StellarFeeRow.js b/src/families/stellar/StellarFeeRow.js
index 273f83d591..93e199de61 100644
--- a/src/families/stellar/StellarFeeRow.js
+++ b/src/families/stellar/StellarFeeRow.js
@@ -1,62 +1,155 @@
// @flow
import React, { useCallback } from "react";
-import { View, StyleSheet, Linking } from "react-native";
-import type { AccountLike } from "@ledgerhq/live-common/lib/types";
+import {
+ View,
+ StyleSheet,
+ Linking,
+ TouchableOpacity,
+ SafeAreaView,
+ Text,
+} from "react-native";
+import type { AccountLike, Account } from "@ledgerhq/live-common/lib/types";
import { Trans } from "react-i18next";
import type { Transaction } from "@ledgerhq/live-common/lib/families/stellar/types";
import {
- getAccountUnit,
+ getMainAccount,
getAccountCurrency,
} from "@ledgerhq/live-common/lib/account";
+import { getAccountBridge } from "@ledgerhq/live-common/lib/bridge";
import { useTheme } from "@react-navigation/native";
import SummaryRow from "../../screens/SendFunds/SummaryRow";
import LText from "../../components/LText";
+import CheckBox from "../../components/CheckBox";
import CurrencyUnitValue from "../../components/CurrencyUnitValue";
import CounterValue from "../../components/CounterValue";
+import SectionSeparator from "../../components/SectionSeparator";
import ExternalLink from "../../icons/ExternalLink";
import { urls } from "../../config/urls";
+import { ScreenName } from "../../const";
type Props = {
account: AccountLike,
transaction: Transaction,
+ parentAccount: Account,
+ navigation: *,
+ route: { params: * },
+ setTransaction: Function,
};
-export default function StellarFeeRow({ account, transaction }: Props) {
+export default function StellarFeeRow({
+ account,
+ parentAccount,
+ transaction,
+ navigation,
+ route,
+ setTransaction,
+}: Props) {
const { colors } = useTheme();
const extraInfoFees = useCallback(() => {
Linking.openURL(urls.feesMoreInfo);
}, []);
if (transaction.family !== "stellar") return null;
+
+ const bridge = getAccountBridge(account, parentAccount);
+ const suggestedFee = transaction.networkInfo.fees;
const fees = transaction.fees;
- const unit = getAccountUnit(account);
+
+ const isCustomFee = !fees.eq(suggestedFee);
+
+ const mainAccount = getMainAccount(account, parentAccount);
const currency = getAccountCurrency(account);
- return (
- }
- additionalInfo={
-
-
-
- }
+ const onFeeModeChange = (isCustom: boolean) => {
+ if (isCustom) {
+ navigation.navigate(ScreenName.StellarEditCustomFees, {
+ ...route.params,
+ accountId: account.id,
+ transaction,
+ });
+ } else {
+ setTransaction(
+ bridge.updateTransaction(transaction, {
+ fees: suggestedFee,
+ }),
+ );
+ }
+ };
+
+ const FeeItem = ({
+ label,
+ isSelected,
+ fee,
+ onSelect,
+ }: {
+ label: React.ReactNode,
+ isSelected: boolean,
+ fee: BigNumber,
+ onSelect: (isCustom: boolean) => void,
+ }) => (
+
-
-
- {fees ? (
-
-
-
- ) : null}
+
+
+
+
+ {label}
+
+
+
+
+ {fee ? (
+
+
+
+ ) : null}
+
+
+ {fee ? (
+
+ ) : null}
+
-
- {fees ? (
-
- ) : null}
-
-
+
+ );
+
+ return (
+
+
+ }
+ additionalInfo={
+
+
+
+ }
+ />
+
+
+ }
+ isSelected={!isCustomFee}
+ fee={suggestedFee}
+ onSelect={() => onFeeModeChange(false)}
+ />
+ }
+ isSelected={isCustomFee}
+ fee={isCustomFee ? fees : null}
+ onSelect={() => onFeeModeChange(true)}
+ />
+
+
);
}
@@ -65,9 +158,12 @@ const styles = StyleSheet.create({
flex: 1,
flexDirection: "row",
},
- summaryRowText: {
- fontSize: 16,
- textAlign: "right",
+ feesPickerContainer: {
+ flex: 1,
+ marginBottom: 16,
+ },
+ feesAmountContainer: {
+ alignItems: "flex-end",
},
countervalue: {
fontSize: 12,
@@ -75,4 +171,30 @@ const styles = StyleSheet.create({
valueText: {
fontSize: 16,
},
+ feeButton: {
+ width: "100%",
+ borderRadius: 4,
+ borderWidth: 1,
+ marginVertical: 4,
+ padding: 16,
+ flexDirection: "row",
+ alignItems: "center",
+ },
+ feeContainer: {
+ flex: 1,
+ flexDirection: "row",
+ justifyContent: "space-between",
+ alignItems: "center",
+ },
+ leftBox: {
+ flex: 1,
+ flexDirection: "row",
+ alignItems: "center",
+ },
+ feeLabel: { fontSize: 16, textTransform: "capitalize", marginLeft: 10 },
+ checkbox: {
+ borderRadius: 24,
+ width: 20,
+ height: 20,
+ },
});
diff --git a/src/families/stellar/SubAccountList.js b/src/families/stellar/SubAccountList.js
new file mode 100644
index 0000000000..6bdcb8a744
--- /dev/null
+++ b/src/families/stellar/SubAccountList.js
@@ -0,0 +1,103 @@
+// @flow
+import React, { useCallback } from "react";
+import { StyleSheet, View } from "react-native";
+import { Trans } from "react-i18next";
+import { useNavigation, useTheme } from "@react-navigation/native";
+import { useSelector } from "react-redux";
+
+import IconPlus from "../../icons/Plus";
+import Button from "../../components/Button";
+import { NavigatorName, ScreenName } from "../../const";
+import LText from "../../components/LText";
+import { accountScreenSelector } from "../../reducers/accounts";
+
+const ReceiveButton = ({ accountId }: { accountId: string }) => {
+ const { colors } = useTheme();
+ const navigation = useNavigation();
+ const onReceiveClick = useCallback(() => {
+ navigation.navigate(NavigatorName.StellarAddAssetFlow, {
+ screen: ScreenName.StellarAddAssetSelectAsset,
+ params: { accountId },
+ });
+ }, [navigation, accountId]);
+ return (
+