Skip to content

Commit 0cee45c

Browse files
committed
feat(suite-native): add eip1559 custom fee inputs
1 parent 1773ad0 commit 0cee45c

File tree

6 files changed

+104
-23
lines changed

6 files changed

+104
-23
lines changed

suite-native/transaction-management/src/components/fees/CustomFee/CustomFeeInputs.tsx

Lines changed: 57 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { G } from '@mobily/ts-belt';
44

55
import { NetworkSymbol, getNetworkType } from '@suite-common/wallet-config';
66
import { FeesRootState, selectConvertedNetworkFeeInfo } from '@suite-common/wallet-core';
7-
import { getFeeUnits } from '@suite-common/wallet-utils';
7+
import { getFeeUnits, isEip1559 } from '@suite-common/wallet-utils';
88
import { Hint, Text, VStack } from '@suite-native/atoms';
99
import { TextInputField, useFormContext } from '@suite-native/forms';
1010
import { integerTransformer, useAmountInputTransformers } from '@suite-native/helpers';
@@ -32,11 +32,14 @@ export const CustomFeeInputs = ({ symbol }: CustomFeeInputsProps) => {
3232

3333
const customFeeLimitName = 'customFeeLimit';
3434
const feePerUnitFieldName = 'customFeePerUnit';
35+
const maxFeePerGasFieldName = 'customMaxFeePerGas';
36+
const maxPriorityFeePerGasFieldName = 'customMaxPriorityFeePerGas';
3537
const hasFeePerByteError = G.isNotNullable(errors[feePerUnitFieldName]);
3638

3739
const networkType = getNetworkType(symbol);
3840
const feeUnits = getFeeUnits(networkType);
3941
const formattedFeePerUnit = `${feeInfo?.minFee} ${feeUnits}`;
42+
const isEip1559Fee = networkType === 'ethereum' && isEip1559(feeInfo?.levels[0]);
4043

4144
const handleFieldChangeValue =
4245
(fieldName: keyof FeesFormValues, transformer: (value: string) => string) =>
@@ -61,19 +64,59 @@ export const CustomFeeInputs = ({ symbol }: CustomFeeInputsProps) => {
6164
onChangeText={handleFieldChangeValue(customFeeLimitName, integerTransformer)}
6265
/>
6366
)}
64-
<TextInputField
65-
label={
66-
networkType === 'ethereum'
67-
? translate('transactionManagement.fees.custom.bottomSheet.label.gasPrice')
68-
: translate('transactionManagement.fees.custom.bottomSheet.label.feeRate')
69-
}
70-
name={feePerUnitFieldName}
71-
testID={`@transactionManagement/${feePerUnitFieldName}-input`}
72-
accessibilityLabel="address input"
73-
keyboardType={networkType === 'bitcoin' ? 'decimal-pad' : 'number-pad'}
74-
rightIcon={<Text color="textSubdued">{feeUnits}</Text>}
75-
onChangeText={handleFieldChangeValue(feePerUnitFieldName, cryptoAmountTransformer)}
76-
/>
67+
{isEip1559Fee ? (
68+
<>
69+
<TextInputField
70+
label={translate(
71+
'transactionManagement.fees.custom.bottomSheet.label.maxFeePerGas',
72+
)}
73+
name={maxFeePerGasFieldName}
74+
testID={`@transactionManagement/${maxFeePerGasFieldName}-input`}
75+
accessibilityLabel="address input"
76+
keyboardType="number-pad"
77+
rightIcon={<Text color="textSubdued">{feeUnits}</Text>}
78+
onChangeText={handleFieldChangeValue(
79+
maxFeePerGasFieldName,
80+
integerTransformer,
81+
)}
82+
/>
83+
<TextInputField
84+
label={translate(
85+
'transactionManagement.fees.custom.bottomSheet.label.maxPriorityFeePerGas',
86+
)}
87+
name={maxPriorityFeePerGasFieldName}
88+
testID={`@transactionManagement/${maxPriorityFeePerGasFieldName}-input`}
89+
accessibilityLabel="address input"
90+
rightIcon={<Text color="textSubdued">{feeUnits}</Text>}
91+
keyboardType="number-pad"
92+
onChangeText={handleFieldChangeValue(
93+
maxPriorityFeePerGasFieldName,
94+
integerTransformer,
95+
)}
96+
/>
97+
</>
98+
) : (
99+
<TextInputField
100+
label={
101+
networkType === 'ethereum'
102+
? translate(
103+
'transactionManagement.fees.custom.bottomSheet.label.gasPrice',
104+
)
105+
: translate(
106+
'transactionManagement.fees.custom.bottomSheet.label.feeRate',
107+
)
108+
}
109+
name={feePerUnitFieldName}
110+
testID={`@transactionManagement/${feePerUnitFieldName}-input`}
111+
accessibilityLabel="address input"
112+
keyboardType={networkType === 'bitcoin' ? 'decimal-pad' : 'number-pad'}
113+
rightIcon={<Text color="textSubdued">{feeUnits}</Text>}
114+
onChangeText={handleFieldChangeValue(
115+
feePerUnitFieldName,
116+
cryptoAmountTransformer,
117+
)}
118+
/>
119+
)}
77120
{networkType !== 'ethereum' && !hasFeePerByteError && (
78121
<Hint variant="info">
79122
<Translation

suite-native/transaction-management/src/feesFormSchema.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,9 @@ export const feesFormValidationSchema = yup.object({
9191
return feeBig.gte(minimalFeeLimit);
9292
},
9393
),
94+
// FIXME: add validations
95+
customMaxFeePerGas: yup.string(),
96+
customMaxPriorityFeePerGas: yup.string(),
9497
});
9598

9699
export type FeesFormValues = yup.InferType<typeof feesFormValidationSchema>;

suite-native/transaction-management/src/hooks/fees/useCustomFee.ts

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ type UseCustomFeeProps = {
2424

2525
const FEE_PER_UNIT_FIELD_NAME = 'customFeePerUnit';
2626
const FEE_LIMIT_FIELD_NAME = 'customFeeLimit';
27+
const MAX_FEE_PER_GAS_FIELD_NAME = 'customMaxFeePerGas';
28+
const MAX_PRIORITY_FEE_PER_GAS_FIELD_NAME = 'customMaxPriorityFeePerGas';
2729

2830
export const useCustomFee = ({ accountKey, formState }: UseCustomFeeProps) => {
2931
const debounce = useDebounce();
@@ -47,10 +49,13 @@ export const useCustomFee = ({ accountKey, formState }: UseCustomFeeProps) => {
4749
watch,
4850
} = useFormContext<FeesFormValues>();
4951

50-
const { customFeePerUnit, customFeeLimit } = getValues();
52+
const { customFeePerUnit, customFeeLimit, customMaxFeePerGas, customMaxPriorityFeePerGas } =
53+
getValues();
5154

5255
const watchedFeePerUnit = watch(FEE_PER_UNIT_FIELD_NAME, '0');
5356
const watchedFeeLimit = watch(FEE_LIMIT_FIELD_NAME, '1') as string;
57+
const watchedMaxFeePerGas = watch(MAX_FEE_PER_GAS_FIELD_NAME, '0');
58+
const watchedMaxPriorityFeePerGas = watch(MAX_PRIORITY_FEE_PER_GAS_FIELD_NAME, '0');
5459

5560
const normalLevelTransactionBytes = useSelector((state: NativeSendRootState) =>
5661
selectFeeLevelTransactionBytes(state, 'normal'),
@@ -78,6 +83,8 @@ export const useCustomFee = ({ accountKey, formState }: UseCustomFeeProps) => {
7883
selectedFeeLevel: 'custom',
7984
customFeePerUnit,
8085
customFeeLimit,
86+
customMaxPriorityFeePerGas,
87+
customMaxFeePerGas,
8188
}),
8289
);
8390

@@ -94,20 +101,30 @@ export const useCustomFee = ({ accountKey, formState }: UseCustomFeeProps) => {
94101
setIsFeeLoading(false);
95102
}, [
96103
trigger,
104+
networkType,
97105
customFeePerUnit,
98106
formState,
99-
customFeeLimit,
100107
dispatch,
101108
accountKey,
102-
networkType,
109+
customFeeLimit,
110+
customMaxPriorityFeePerGas,
111+
customMaxFeePerGas,
103112
setError,
104113
translate,
105114
]);
106115

107116
useEffect(() => {
108117
setIsFeeLoading(true);
109118
debounce(handleValuesChange);
110-
}, [watchedFeePerUnit, watchedFeeLimit, handleValuesChange, debounce, networkType]);
119+
}, [
120+
watchedFeePerUnit,
121+
watchedFeeLimit,
122+
handleValuesChange,
123+
debounce,
124+
networkType,
125+
watchedMaxFeePerGas,
126+
watchedMaxPriorityFeePerGas,
127+
]);
111128

112129
// If the trezor-connect is unable to compose the transaction, we display rough estimate of the fee instead.
113130
const feeEstimate = useMemo(

suite-native/transaction-management/src/hooks/fees/useFeeCalculation.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ export const useFeeCalculation = ({
4040
const feeLevels = useSelector(selectFeeLevels);
4141
const { symbol } = account ?? {};
4242

43+
const normalFee = isFinalPrecomposedTransaction(feeLevels.normal)
44+
? (feeLevels.normal as PrecomposedTransactionFinal)
45+
: null;
46+
4347
const form = useFeesForm({
4448
accountKey,
4549
defaultFeeLevel: selectedFee,
@@ -55,10 +59,6 @@ export const useFeeCalculation = ({
5559
selectConvertedNetworkFeeLevelFeePerUnit(state, symbol, selectedFeeLevel),
5660
);
5761

58-
const normalFee = isFinalPrecomposedTransaction(feeLevels.normal)
59-
? (feeLevels.normal as PrecomposedTransactionFinal)
60-
: null;
61-
6262
const { areFeesLoading } = useFeesFetching({
6363
networkSymbol: symbol,
6464
isRefetchDisabled: selectedFeeLevel === 'custom' || selectedSetMaxOutputId !== undefined,

suite-native/transaction-management/src/hooks/fees/useFeesForm.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ export const useFeesForm = ({
5757
feeLevel: defaultFeeLevel,
5858
customFeePerUnit: trimmedFeePerUnit,
5959
customFeeLimit: normalFee?.feeLimit,
60+
customMaxFeePerGas: normalFee?.maxFeePerGas,
61+
customMaxPriorityFeePerGas: normalFee?.maxPriorityFeePerGas,
6062
},
6163
context: {
6264
networkFeeInfo,

suite-native/transaction-management/src/thunks.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,12 +75,22 @@ export const calculateCustomFeeLevelThunk = createThunk<
7575
selectedFeeLevel?: 'custom';
7676
customFeePerUnit?: string;
7777
customFeeLimit?: string;
78+
customMaxFeePerGas?: string;
79+
customMaxPriorityFeePerGas?: string;
7880
},
7981
{ rejectValue: string }
8082
>(
8183
`${TRANSACTION_MANAGEMENT_PREFIX}/calculateCustomFeeLevelThunk`,
8284
async (
83-
{ accountKey, formState, selectedFeeLevel, customFeePerUnit, customFeeLimit },
85+
{
86+
accountKey,
87+
formState,
88+
selectedFeeLevel,
89+
customFeePerUnit,
90+
customFeeLimit,
91+
customMaxFeePerGas,
92+
customMaxPriorityFeePerGas,
93+
},
8494
{ dispatch, getState, fulfillWithValue, rejectWithValue },
8595
) => {
8696
const account = selectAccountByKey(getState(), accountKey);
@@ -106,6 +116,12 @@ export const calculateCustomFeeLevelThunk = createThunk<
106116
if (customFeeLimit) {
107117
formStateCopy.feeLimit = customFeeLimit;
108118
}
119+
if (customMaxFeePerGas) {
120+
formStateCopy.maxFeePerGas = customMaxFeePerGas;
121+
}
122+
if (customMaxPriorityFeePerGas) {
123+
formStateCopy.maxPriorityFeePerGas = customMaxPriorityFeePerGas;
124+
}
109125

110126
const response = await dispatch(
111127
composeSendFormTransactionFeeLevelsThunk({

0 commit comments

Comments
 (0)