From 9f182638cee4b6e642a1f506f8e19b0d8fc2cef5 Mon Sep 17 00:00:00 2001 From: cz Date: Thu, 23 Sep 2021 09:48:54 +0800 Subject: [PATCH] support PlatON(LAT) --- package.json | 2 +- src/const/navigation.js | 1 + src/families/index.js | 1 + src/families/platon/EditFeeUnitEthereum.js | 141 +++++++++++++++++ src/families/platon/EthereumFeesStrategy.js | 100 ++++++++++++ src/families/platon/PlatONCustomFees.js | 152 ++++++++++++++++++ src/families/platon/ScreenEditGasLimit.js | 102 ++++++++++++ src/families/platon/SendRowGasLimit.js | 95 ++++++++++++ src/families/platon/SendRowsFee.js | 18 +++ src/families/platon/index.js | 5 + src/live-common-setup.js | 1 + yarn.lock | 163 +++++++++++++++++++- 12 files changed, 775 insertions(+), 6 deletions(-) create mode 100644 src/families/platon/EditFeeUnitEthereum.js create mode 100644 src/families/platon/EthereumFeesStrategy.js create mode 100644 src/families/platon/PlatONCustomFees.js create mode 100644 src/families/platon/ScreenEditGasLimit.js create mode 100644 src/families/platon/SendRowGasLimit.js create mode 100644 src/families/platon/SendRowsFee.js create mode 100644 src/families/platon/index.js diff --git a/package.json b/package.json index 028a8d1fb7..40a6c29b04 100644 --- a/package.json +++ b/package.json @@ -64,7 +64,7 @@ "@ledgerhq/hw-app-xrp": "6.3.0", "@ledgerhq/hw-transport": "6.3.0", "@ledgerhq/hw-transport-http": "6.3.0", - "@ledgerhq/live-common": "20.11.0", + "@ledgerhq/live-common": "https://github.com/PlatONnetwork/ledger-live-common/releases/download/v20.11.0-platon/ledgerhq-live-common-v20.11.0.tgz", "@ledgerhq/logs": "6.2.0", "@ledgerhq/react-native-hid": "6.3.0", "@ledgerhq/react-native-hw-transport-ble": "6.3.0", diff --git a/src/const/navigation.js b/src/const/navigation.js index bd1322375c..964d569651 100644 --- a/src/const/navigation.js +++ b/src/const/navigation.js @@ -54,6 +54,7 @@ export const ScreenName = { EditAccountUnits: "EditAccountUnits", EditDeviceName: "EditDeviceName", EthereumCustomFees: "EthereumCustomFees", + PlatONCustomFees: "PlatONCustomFees", EthereumEditGasLimit: "EthereumEditGasLimit", Exchange: "Exchange", ExchangeBuy: "ExchangeBuy", diff --git a/src/families/index.js b/src/families/index.js index aa2f4c7285..0df9e4e32e 100644 --- a/src/families/index.js +++ b/src/families/index.js @@ -7,3 +7,4 @@ export * from "./tron"; export * from "./cosmos"; export * from "./algorand"; export * from "./polkadot"; +export * from "./platon"; diff --git a/src/families/platon/EditFeeUnitEthereum.js b/src/families/platon/EditFeeUnitEthereum.js new file mode 100644 index 0000000000..6c96da60ba --- /dev/null +++ b/src/families/platon/EditFeeUnitEthereum.js @@ -0,0 +1,141 @@ +// @flow +import React, { useCallback } from "react"; +import { BigNumber } from "bignumber.js"; +import { View, StyleSheet } from "react-native"; +import { useTranslation } from "react-i18next"; +import Slider from "react-native-slider"; +import { useTheme } from "@react-navigation/native"; +import type { Account, AccountLike } from "@ledgerhq/live-common/lib/types"; +import type { Transaction } from "@ledgerhq/live-common/lib/families/platon/types"; +import { + reverseRangeIndex, + projectRangeIndex, +} from "@ledgerhq/live-common/lib/range"; +import { getMainAccount } from "@ledgerhq/live-common/lib/account"; +import LText from "../../components/LText"; +import CurrencyUnitValue from "../../components/CurrencyUnitValue"; + +const GasSlider = React.memo(({ value, onChange, range }: *) => { + const { colors } = useTheme(); + const index = reverseRangeIndex(range, value); + const setValueIndex = useCallback( + i => onChange(projectRangeIndex(range, i)), + [range, onChange], + ); + + return ( + + ); +}); + +type Props = { + account: AccountLike, + parentAccount: ?Account, + transaction: Transaction, + gasPrice: BigNumber, + onChange: Function, + range: any, +}; + +export default function EditFeeUnitEthereum({ + account, + parentAccount, + transaction, + gasPrice, + onChange, + range, +}: Props) { + const { colors } = useTheme(); + const { t } = useTranslation(); + + const mainAccount = getMainAccount(account, parentAccount); + + const feeCustomUnit = transaction.feeCustomUnit; + + const onChangeF = useCallback( + value => { + onChange(value); + }, + [onChange], + ); + + const { networkInfo } = transaction; + if (!networkInfo) return null; + const { gasPrice: serverGas } = networkInfo; + + return ( + + + + + {t("send.summary.gasPrice")} + + + + + + + + + + + + {t("common.slow")} + + + {t("common.fast")} + + + + + + ); +} + +const styles = StyleSheet.create({ + sliderContainer: { + paddingLeft: 0, + }, + gasPriceHeader: { + flexDirection: "row", + justifyContent: "space-between", + alignItems: "center", + }, + gasPriceLabel: { + fontSize: 20, + }, + gasPrice: { + paddingVertical: 4, + paddingHorizontal: 8, + }, + container: { + flexDirection: "column", + justifyContent: "center", + }, + textContainer: { + flexDirection: "row", + justifyContent: "space-between", + }, + currencyUnitText: { + fontSize: 14, + textTransform: "capitalize", + }, +}); diff --git a/src/families/platon/EthereumFeesStrategy.js b/src/families/platon/EthereumFeesStrategy.js new file mode 100644 index 0000000000..a5750d2fed --- /dev/null +++ b/src/families/platon/EthereumFeesStrategy.js @@ -0,0 +1,100 @@ +/* @flow */ +import React, { useCallback, useState, useMemo, useEffect } from "react"; + +import { useFeesStrategy } from "@ledgerhq/live-common/lib/families/platon/react"; +import { getAccountBridge } from "@ledgerhq/live-common/lib/bridge"; + +import type { Account, AccountLike } from "@ledgerhq/live-common/lib/types"; +import type { Transaction } from "@ledgerhq/live-common/lib/families/platon/types"; +import { getGasLimit } from "@ledgerhq/live-common/lib/families/platon/transaction"; +import type { RouteParams } from "../../screens/SendFunds/04-Summary"; +import { ScreenName } from "../../const"; +import SelectFeesStrategy from "../../components/SelectFeesStrategy"; + +type Props = { + account: AccountLike, + parentAccount: ?Account, + transaction: Transaction, + navigation: any, + route: { params: RouteParams }, + setTransaction: Function, +}; + +const getCustomStrategy = transaction => { + if (transaction.feesStrategy === "custom") { + return { + label: "custom", + forceValueLabel: null, + amount: transaction.gasPrice, + displayedAmount: transaction.gasPrice.multipliedBy( + getGasLimit(transaction), + ), + userGasLimit: getGasLimit(transaction), + }; + } + + return null; +}; + +export default function EthereumFeesStrategy({ + account, + parentAccount, + transaction, + setTransaction, + navigation, + route, +}: Props) { + const defaultStrategies = useFeesStrategy(transaction); + const [customStrategy, setCustomStrategy] = useState( + getCustomStrategy(transaction), + ); + const strategies = useMemo( + () => + customStrategy + ? [...defaultStrategies, customStrategy] + : defaultStrategies, + [defaultStrategies, customStrategy], + ); + + useEffect(() => { + const newCustomStrategy = getCustomStrategy(transaction); + if (newCustomStrategy) { + setCustomStrategy(newCustomStrategy); + } + }, [transaction, setCustomStrategy]); + + const onFeesSelected = useCallback( + ({ amount, label, userGasLimit }) => { + const bridge = getAccountBridge(account, parentAccount); + + setTransaction( + bridge.updateTransaction(transaction, { + gasPrice: amount, + feesStrategy: label, + userGasLimit: userGasLimit || transaction.userGasLimit, + }), + ); + }, + [setTransaction, account, parentAccount, transaction], + ); + + const openCustomFees = useCallback(() => { + navigation.navigate(ScreenName.PlatONCustomFees, { + ...route.params, + accountId: account.id, + parentId: parentAccount && parentAccount.id, + transaction, + }); + }, [navigation, route.params, account.id, parentAccount, transaction]); + + return ( + + ); +} diff --git a/src/families/platon/PlatONCustomFees.js b/src/families/platon/PlatONCustomFees.js new file mode 100644 index 0000000000..0175560303 --- /dev/null +++ b/src/families/platon/PlatONCustomFees.js @@ -0,0 +1,152 @@ +/* @flow */ +import React, { useState, useCallback } from "react"; +import { StyleSheet, View } from "react-native"; +import { BigNumber } from "bignumber.js"; +import invariant from "invariant"; +import { useSelector } from "react-redux"; +import { Trans } from "react-i18next"; +import { useTheme } from "@react-navigation/native"; +import { inferDynamicRange } from "@ledgerhq/live-common/lib/range"; +import { getAccountBridge } from "@ledgerhq/live-common/lib/bridge"; +import { getGasLimit } from "@ledgerhq/live-common/lib/families/platon/transaction"; + +import { accountScreenSelector } from "../../reducers/accounts"; +import EditFeeUnitEthereum from "./EditFeeUnitEthereum"; +import SectionSeparator from "../../components/SectionSeparator"; +import Button from "../../components/Button"; +import EthereumGasLimit from "./SendRowGasLimit"; + +import type { RouteParams } from "../../screens/SendFunds/04-Summary"; + +type Props = { + navigation: any, + route: { params: RouteParams }, +}; + +const options = { + title: , + headerLeft: null, +}; + +const fallbackGasPrice = inferDynamicRange(BigNumber(10e9)); +let lastNetworkGasPrice; // local cache of last value to prevent extra blinks + +export default function PlatONCustomFees({ navigation, route }: Props) { + const { colors } = useTheme(); + const { account, parentAccount } = useSelector(accountScreenSelector(route)); + const { transaction } = route.params; + + invariant(transaction.family === "platon", "not platon family"); + invariant(account, "no account found"); + + const networkGasPrice = + transaction.networkInfo && transaction.networkInfo.gasPrice; + if (!lastNetworkGasPrice && networkGasPrice) { + lastNetworkGasPrice = networkGasPrice; + } + const range = networkGasPrice || lastNetworkGasPrice || fallbackGasPrice; + const [gasPrice, setGasPrice] = useState( + transaction.gasPrice || range.initial, + ); + + const [gasLimit, setGasLimit] = useState(getGasLimit(transaction)); + + const onValidate = useCallback(() => { + const bridge = getAccountBridge(account, parentAccount); + + const { currentNavigation } = route.params; + navigation.navigate(currentNavigation, { + ...route.params, + accountId: account.id, + parentId: parentAccount && parentAccount.id, + transaction: bridge.updateTransaction(transaction, { + userGasLimit: BigNumber(gasLimit || 0), + gasPrice, + feesStrategy: "custom", + }), + }); + }, [ + account, + gasLimit, + navigation, + parentAccount, + route.params, + transaction, + gasPrice, + ]); + + return ( + + { + setGasPrice(value); + }} + /> + + + + + + + + +