Skip to content

Commit

Permalink
feat: support send max. (#277)
Browse files Browse the repository at this point in the history
* feat: support send max.

* style: tuning.

* style: tuning for gas reserved.

* feat: keep same logic with rabby extension.

---
- fix: intrinsic_gas_too_low
- feat: not warning gas fee reservation.
- feat: change decimals for balance text.

* feat: no reserve gas when send max native token.

* feat: gasless failure tips (#279)

* feat: gasless failture tips

* feat: points toast

* feat: swap max

---------

Co-authored-by: DMY <[email protected]>
  • Loading branch information
richardo2016x and dmy147 authored Jun 5, 2024
1 parent 97884b7 commit e398d6b
Show file tree
Hide file tree
Showing 36 changed files with 513 additions and 201 deletions.
2 changes: 1 addition & 1 deletion apps/mobile/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
"@rabby-wallet/eth-walletconnect-keyring": "2.1.3",
"@rabby-wallet/object-multiplex": "workspace:^",
"@rabby-wallet/persist-store": "workspace:^",
"@rabby-wallet/rabby-api": "0.7.14",
"@rabby-wallet/rabby-api": "0.7.15",
"@rabby-wallet/rabby-security-engine": "^1.1.17",
"@rabby-wallet/rabby-swap": "0.0.36",
"@rabby-wallet/service-address": "workspace:^",
Expand Down
18 changes: 18 additions & 0 deletions apps/mobile/src/assets/icons/sign/tx/question-cc.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 8 additions & 3 deletions apps/mobile/src/assets/locales/en/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -299,10 +299,13 @@
"importedByLedger": "Imported by Ledger",
"signAndSubmitButton": "Sign and Create",
"gasless": {
"unavailable": "Gas balance is not enough for this transaction",
"unavailable": "Gas is not enough and not qualify for Free Gas",
"notEnough": "Gas balance is not enough",
"GetFreeGasToSign": "Get Free Gas to sign",
"rabbyPayGas": "Rabby'll pay for the gas needed – just sign on"
"rabbyPayGas": "Rabby'll pay for the gas needed – just sign on",
"customRpcUnavailableTip": "Custom RPCs are not supported for Free Gas",
"walletConnectUnavailableTip": "Mobile wallet connected via WalletConnect is not supported for Free Gas",
"watchUnavailableTip": "Watch-only address is not supported for Free Gas"
},
"walletConnect": {
"connectedButCantSign": "Connected but unable to sign.",
Expand Down Expand Up @@ -1881,7 +1884,9 @@
"sign": "Sign"
}
},
"code-set-successfully": "Referral code set successfully"
"code-set-successfully": "Referral code set successfully",
"initialPointsClaimEnded": "Initial Points claim ended",
"firstRoundEnded": "🎉 The first round of Rabby Points has ended"
}
},
"component": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { AppColorsVariants } from '@/constant/theme';
import { useThemeColors } from '@/hooks/theme';
import ModalPreviewNFTItem from '@/components/ModalPreviewNFTItem';
import { AppBottomSheetModal } from '@/components/customized/BottomSheet';
import { ModalLayouts } from '@/constant/layout';

const getStyles = (colors: AppColorsVariants) =>
StyleSheet.create({
Expand Down Expand Up @@ -103,7 +104,7 @@ const NFTWithName = ({
visible={!!focusingNFT}
nft={focusingNFT as unknown as TransferingNFTItem}
onDismiss={() => setFocusingNFT(null)}
snapPoints={['80%']}
snapPoints={[ModalLayouts.defaultHeightPercentText]}
/>
)}
</>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ interface Props extends Omit<ActionGroupProps, 'account'> {
showGasLess?: boolean;
enableGasLess?: () => void;
canUseGasLess?: boolean;
gasLessFailedReason?: string;
isWatchAddr?: boolean;
}

const getStyles = (colors: AppColorsVariants) =>
Expand Down Expand Up @@ -169,7 +171,8 @@ export const FooterBar: React.FC<Props> = ({
canUseGasLess = false,
onIgnoreAllRules,
enableGasLess,

gasLessFailedReason,
isWatchAddr,
...props
}) => {
const [account, setAccount] = React.useState<Account>();
Expand Down Expand Up @@ -378,8 +381,8 @@ export const FooterBar: React.FC<Props> = ({
enableGasLess?.();
}}
/>
) : (
<GasLessNotEnough />
) : isWatchAddr ? null : (
<GasLessNotEnough gasLessFailedReason={gasLessFailedReason} />
))}
</View>
</View>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { PropsWithChildren, useEffect, useMemo, useState } from 'react';
import { default as RcIconGasLight } from '@/assets/icons/sign/tx/gas-light.svg';
import { default as RcIconGasDark } from '@/assets/icons/sign/tx/gas-dark.svg';
import { default as RcIconQuestion } from '@/assets/icons/sign/tx/question-cc.svg';

import { useTranslation } from 'react-i18next';
import { default as RcIconLogo } from '@/assets/icons/sign/tx/rabby.svg';
Expand All @@ -17,6 +18,7 @@ import {
ViewStyle,
DimensionValue,
StyleSheet,
Pressable,
} from 'react-native';
import { makeThemeIcon } from '@/hooks/makeThemeIcon';
import LinearGradient from 'react-native-linear-gradient';
Expand All @@ -33,26 +35,49 @@ import Animated, {
} from 'react-native-reanimated';
import { renderText } from '@/utils/renderNode';
import { colord } from 'colord';
import { Tip } from '@/components/Tip';

const RcIconGas = makeThemeIcon(RcIconGasLight, RcIconGasDark);

export function GasLessNotEnough() {
export function GasLessNotEnough({
gasLessFailedReason,
}: {
gasLessFailedReason?: string;
}) {
const { t } = useTranslation();
const colors = useThemeColors();
const styles = useMemo(() => getStyles(colors), [colors]);
const [visible, setVisible] = useState(false);

return (
<View style={styles.securityLevelTip}>
<Pressable
style={[styles.securityLevelTip, { paddingHorizontal: 8 }]}
onPress={() => setVisible(true)}>
<View style={styles.tipTriangle} />
<RcIconGas
width={16}
height={16}
color={colors['neutral-title-1']}
style={{ marginRight: 4 }}
/>
<Text style={styles.text}>
<Text style={[styles.text, { marginHorizontal: 4, marginRight: 6 }]}>
{t('page.signFooterBar.gasless.unavailable')}
</Text>
</View>
{gasLessFailedReason ? (
<Tip
content={gasLessFailedReason}
isVisible={visible}
onClose={() => {
setVisible(false);
}}>
<RcIconQuestion
color={colors['neutral-foot']}
width={14}
height={14}
/>
</Tip>
) : null}
</Pressable>
);
}

Expand Down Expand Up @@ -341,9 +366,9 @@ const getStyles = createGetStyles(colors => ({
borderRightColor: 'transparent',
borderTopColor: 'transparent',
borderBottomColor: colors['neutral-card-2'],
alignItems: 'center',
},
text: {
flex: 1,
color: colors['neutral-title-1'],
fontSize: 12,
fontWeight: '500',
Expand Down Expand Up @@ -372,6 +397,7 @@ const getStyles = createGetStyles(colors => ({
color: colors['neutral-card-2'],
},
gasText: {
flex: 1,
color: colors['neutral-title-1'],
},
linearGradient: {
Expand Down
26 changes: 25 additions & 1 deletion apps/mobile/src/components/Approval/components/SignTx/SignTx.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,10 @@ export const SignTx = ({ params, origin }: SignTxProps) => {
const [canUseGasLess, setCanUseGasLess] = useState(false);
const [useGasLess, setUseGasLess] = useState(false);

const [gasLessFailedReason, setGasLessFailedReason] = useState<
string | undefined
>(undefined);

// const [isGnosisAccount, setIsGnosisAccount] = useState(false);
// const [isCoboArugsAccount, setIsCoboArugsAccount] = useState(false);
const isGnosisAccount = false;
Expand Down Expand Up @@ -382,15 +386,32 @@ export const SignTx = ({ params, origin }: SignTxProps) => {
const isNotWatchAddress =
currentAccountType !== KEYRING_TYPE.WatchAddressKeyring;

if (!isNotWalletConnect) {
setGasLessFailedReason(
t('page.signFooterBar.gasless.walletConnectUnavailableTip'),
);
}

if (!isNotWatchAddress) {
setGasLessFailedReason(
t('page.signFooterBar.gasless.watchUnavailableTip'),
);
}

return isNotWatchAddress && isNotWalletConnect;
}, [currentAccountType]);
}, [currentAccountType, t]);

const [noCustomRPC, setNoCustomRPC] = useState(true);

// useEffect(() => {
// const hasCustomRPC = async () => {
// if (chain?.enum) {
// const b = await wallet.hasCustomRPC(chain?.enum);
// if (b) {
// setGasLessFailedReason(
// t('page.signFooterBar.gasless.customRpcUnavailableTip')
// );
// }
// setNoCustomRPC(!b);
// }
// };
Expand Down Expand Up @@ -818,6 +839,7 @@ export const SignTx = ({ params, origin }: SignTxProps) => {
});

setCanUseGasLess(res.is_gasless);
setGasLessFailedReason(res.desc);
setGasLessLoading(false);
} catch (error) {
console.error('gasLessTxCheck error', error);
Expand Down Expand Up @@ -1160,6 +1182,8 @@ export const SignTx = ({ params, origin }: SignTxProps) => {
</ScrollView>
{txDetail && (
<FooterBar
isWatchAddr={currentAccountType === KEYRING_TYPE.WatchAddressKeyring}
gasLessFailedReason={gasLessFailedReason}
canUseGasLess={canUseGasLess}
showGasLess={!gasLessLoading && isReady && showGasLess}
useGasLess={showGasLess && canUseGasLess && useGasLess}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import { GasSelectContainer } from './GasSelectContainer';
import { FooterButton } from '@/components/FooterButton/FooterButton';
import { TextInput } from 'react-native-gesture-handler';
import { matomoRequestEvent } from '@/utils/analytics';
import { ModalLayouts } from '@/constant/layout';

export interface GasSelectorResponse extends GasLevel {
gasLimit: number;
Expand Down Expand Up @@ -652,7 +653,7 @@ const GasSelector = ({
)}
</View>
<AppBottomSheetModal
snapPoints={['80%']}
snapPoints={[ModalLayouts.defaultHeightPercentText]}
ref={modalRef}
onDismiss={() => setModalVisible(false)}>
<BottomSheetView style={styles.modalWrap}>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { Dimensions, View, Text } from 'react-native';
import { Dimensions, View, Text, Platform } from 'react-native';
import { useTranslation } from 'react-i18next';
import {
BottomSheetBackdrop,
Expand Down Expand Up @@ -29,14 +29,17 @@ import FooterComponentForConfirm from '../customized/FooterComponentForConfirm';
import { MODAL_NAMES } from '../GlobalBottomSheetModal/types';
import ModalConfirmDiscard from './components/ModalConfirmDiscard';
import AppBottomSheetBackdrop from '../patches/BottomSheetBackdrop';
import { ModalLayouts } from '@/constant/layout';

export interface SelectAddressProps {
heightPercent?: `${number}%`;
visible: boolean;
onConfirm?(account: UIContactBookItem): void;
onClose?(options: { behavior: 'canceled' | 'confirmed' }): void;
}

export function SelectAddressSheetModal({
heightPercent = ModalLayouts.defaultHeightPercentText,
visible,
onConfirm,
onClose,
Expand Down Expand Up @@ -175,7 +178,7 @@ export function SelectAddressSheetModal({
<AppBottomSheetModal
ref={sheetModalRef}
index={0}
snapPoints={['70%']}
snapPoints={[heightPercent]}
backgroundStyle={styles.sheet}
enablePanDownToClose={!isEditing}
enableDismissOnClose={true}
Expand Down Expand Up @@ -230,8 +233,8 @@ export function SelectAddressSheetModal({
inWhitelist={inWhitelistLocal || !whitelistEnabled}
isEditing={isEditing}
style={[
idx > 0 && { marginTop: 16 },
idx === arr.length - 1 && { marginBottom: 16 },
idx > 0 && { marginTop: 8 },
idx === arr.length - 1 && { marginBottom: 8 },
]}
onPress={() => {
if (isEditing) {
Expand Down Expand Up @@ -270,7 +273,16 @@ export function SelectAddressSheetModal({

const FOOTER_SIZES = {
buttonHeight: 52,
paddingVertical: 20,
...Platform.select({
ios: {
paddingTop: 16,
paddingBottom: 24,
},
android: {
paddingTop: 16,
paddingBottom: 24,
},
})!,
};

const getStyles = createGetStyles(colors => {
Expand All @@ -279,13 +291,15 @@ const getStyles = createGetStyles(colors => {
backgroundColor: colors['neutral-bg-1'],
},
container: {
paddingVertical: 20,
paddingTop: ModalLayouts.titleTopOffset,
flexDirection: 'column',
position: 'relative',
height: '100%',

paddingBottom:
FOOTER_SIZES.buttonHeight + FOOTER_SIZES.paddingVertical * 2,
FOOTER_SIZES.buttonHeight +
FOOTER_SIZES.paddingTop +
FOOTER_SIZES.paddingBottom,
},
innerBlock: {
paddingHorizontal: 20,
Expand Down Expand Up @@ -324,7 +338,9 @@ const getStyles = createGetStyles(colors => {
borderTopWidth: 0.5,
borderTopStyle: 'solid',
borderTopColor: colors['neutral-line'],
paddingVertical: FOOTER_SIZES.paddingVertical,
backgroundColor: colors['neutral-bg-1'],
paddingTop: FOOTER_SIZES.paddingTop,
paddingBottom: FOOTER_SIZES.paddingBottom,
flexShrink: 0,

position: 'absolute',
Expand Down
3 changes: 2 additions & 1 deletion apps/mobile/src/components/SelectSortedChain/SheetModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { useThemeColors } from '@/hooks/theme';
import { createGetStyles } from '@/utils/styles';

import SelectSortedChain, { SelectSortedChainProps } from './SelectSortedChain';
import { ModalLayouts } from '@/constant/layout';

const getStyles = createGetStyles(colors => {
return {
Expand Down Expand Up @@ -39,7 +40,7 @@ export default function SelectSortedChainModal({
<AppBottomSheetModal
ref={modalRef}
index={0}
snapPoints={['80%']}
snapPoints={[ModalLayouts.defaultHeightPercentText]}
backgroundStyle={styles.sheet}
onDismiss={onCancel}
enableContentPanningGesture={false}>
Expand Down
2 changes: 1 addition & 1 deletion apps/mobile/src/components/Token/TokenAmountInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ export const TokenAmountInput = React.forwardRef<
]}
value={value}
onChangeText={(value: string) => {
onChange(formatSpeicalAmount(value));
onChange?.(formatSpeicalAmount(value));
}}
ref={tokenInputRef}
placeholder="0"
Expand Down
Loading

0 comments on commit e398d6b

Please sign in to comment.