Skip to content

Commit 816379a

Browse files
committed
wip
1 parent fdbbbbf commit 816379a

File tree

21 files changed

+555
-149
lines changed

21 files changed

+555
-149
lines changed

packages/blockchain-link-types/src/blockbook-api.ts

+22
Original file line numberDiff line numberDiff line change
@@ -415,10 +415,32 @@ export interface WsEstimateFeeReq {
415415
value?: string;
416416
};
417417
}
418+
419+
export interface PriorityFeeEstimationDetails {
420+
maxFeePerGas: string;
421+
maxPriorityFeePerGas: string;
422+
minWaitTimeEstimate: number;
423+
maxWaitTimeEstimate: number;
424+
}
425+
426+
export type FeeTrend = 'up' | 'down';
427+
418428
export interface WsEstimateFeeRes {
419429
feePerTx?: string;
420430
feePerUnit?: string;
421431
feeLimit?: string;
432+
eip1559?: {
433+
baseFeePerGas: string;
434+
high: PriorityFeeEstimationDetails;
435+
low: PriorityFeeEstimationDetails;
436+
medium: PriorityFeeEstimationDetails;
437+
networkCongestion: number;
438+
latestPriorityFeeRange: string[];
439+
historicalPriorityFeeRange: string[];
440+
historicalBaseFeeRange: string[];
441+
priorityFeeTrend: FeeTrend;
442+
baseFeeTrend: FeeTrend;
443+
};
422444
}
423445
export interface WsSendTransactionReq {
424446
hex: string;

packages/blockchain-link-types/src/responses.ts

+21
Original file line numberDiff line numberDiff line change
@@ -92,12 +92,33 @@ export interface GetFiatRatesTickersList {
9292
};
9393
}
9494

95+
export interface PriorityFeeEstimationDetails {
96+
maxFeePerGas: string;
97+
maxPriorityFeePerGas: string;
98+
minWaitTimeEstimate: number;
99+
maxWaitTimeEstimate: number;
100+
}
101+
102+
export type FeeTrend = 'up' | 'down';
103+
95104
export interface EstimateFee {
96105
type: typeof RESPONSES.ESTIMATE_FEE;
97106
payload: {
98107
feePerUnit: string;
99108
feePerTx?: string;
100109
feeLimit?: string;
110+
eip1559?: {
111+
baseFeePerGas: string;
112+
low: PriorityFeeEstimationDetails;
113+
medium: PriorityFeeEstimationDetails;
114+
high: PriorityFeeEstimationDetails;
115+
networkCongestion: number;
116+
latestPriorityFeeRange: string[];
117+
historicalPriorityFeeRange: string[];
118+
historicalBaseFeeRange: string[];
119+
priorityFeeTrend: FeeTrend;
120+
baseFeeTrend: FeeTrend;
121+
};
101122
}[];
102123
}
103124

packages/connect/src/api/bitcoin/Fees.ts

+37-13
Original file line numberDiff line numberDiff line change
@@ -82,19 +82,43 @@ export class FeeLevels {
8282
async loadMisc(blockchain: Blockchain) {
8383
try {
8484
const [response] = await blockchain.estimateFee({ blocks: [1] });
85-
// misc coins should have only one FeeLevel (normal)
86-
this.levels[0] = {
87-
...this.levels[0],
88-
...response,
89-
// validate `feePerUnit` from the backend
90-
// should be lower than `coinInfo.maxFee` and higher than `coinInfo.minFee`
91-
// xrp sends values from 1 to very high number occasionally
92-
// see: https://github.com/trezor/trezor-suite/blob/develop/packages/blockchain-link/src/workers/ripple/index.ts#L316
93-
feePerUnit: Math.min(
94-
this.coinInfo.maxFee,
95-
Math.max(this.coinInfo.minFee, parseInt(response.feePerUnit, 10)),
96-
).toString(),
97-
};
85+
if (response.eip1559) {
86+
const eip1559LevelKeys = ['low', 'medium', 'high'] as const;
87+
88+
const { eip1559 } = response;
89+
const eip1559Levels = eip1559LevelKeys.map(levelKey => {
90+
const level = eip1559[levelKey];
91+
92+
return {
93+
label: levelKey,
94+
baseFeePerGas: eip1559.baseFeePerGas,
95+
maxFeePerGas: level.maxFeePerGas,
96+
maxPriorityFeePerGas: level.maxPriorityFeePerGas,
97+
minWaitTimeEstimate: level.minWaitTimeEstimate / 1000, // Infura provides wait time in miliseconds
98+
maxWaitTimeEstimate: level.maxWaitTimeEstimate / 1000,
99+
feePerUnit: '0',
100+
feeLimit: undefined,
101+
ethFeeType: 'eip1559' as const,
102+
blocks: -1,
103+
};
104+
});
105+
106+
this.levels = [...eip1559Levels];
107+
} else {
108+
//misc coins should have only one FeeLevel (normal), for ethereum depends on availability of eip1559
109+
this.levels[0] = {
110+
...this.levels[0],
111+
...response,
112+
// validate `feePerUnit` from the backend
113+
// should be lower than `coinInfo.maxFee` and higher than `coinInfo.minFee`
114+
// xrp sends values from 1 to very high number occasionally
115+
// see: https://github.com/trezor/trezor-suite/blob/develop/packages/blockchain-link/src/workers/ripple/index.ts#L316
116+
feePerUnit: Math.min(
117+
this.coinInfo.maxFee,
118+
Math.max(this.coinInfo.minFee, parseInt(response.feePerUnit, 10)),
119+
).toString(),
120+
};
121+
}
98122
} catch {
99123
// silent
100124
}

packages/connect/src/types/fees.ts

+15
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,14 @@ export const FeeInfo = Type.Object({
88
dustLimit: Type.Number(),
99
});
1010

11+
export type PriorityFeeEstimationDetails = Static<typeof PriorityFeeEstimationDetails>;
12+
export const PriorityFeeEstimationDetails = Type.Object({
13+
maxFeePerGas: Type.String(),
14+
maxPriorityFeePerGas: Type.String(),
15+
maxWaitTimeEstimate: Type.Number(),
16+
minWaitTimeEstimate: Type.Number(),
17+
});
18+
1119
export type FeeLevel = Static<typeof FeeLevel>;
1220
export const FeeLevel = Type.Object({
1321
label: Type.Union([
@@ -16,11 +24,18 @@ export const FeeLevel = Type.Object({
1624
Type.Literal('economy'),
1725
Type.Literal('low'),
1826
Type.Literal('custom'),
27+
Type.Literal('medium'),
1928
]),
29+
ethFeeType: Type.Optional(Type.Union([Type.Literal('legacy'), Type.Literal('eip1559')])),
2030
feePerUnit: Type.String(),
2131
blocks: Type.Number(),
2232
feeLimit: Type.Optional(Type.String()), // eth gas limit
2333
feePerTx: Type.Optional(Type.String()), // fee for BlockchainEstimateFeeParams.request.specific
34+
baseFeePerGas: Type.Optional(Type.String()),
35+
maxFeePerGas: Type.Optional(Type.String()),
36+
maxPriorityFeePerGas: Type.Optional(Type.String()),
37+
maxWaitTimeEstimate: Type.Optional(Type.Number()),
38+
minWaitTimeEstimate: Type.Optional(Type.Number()),
2439
});
2540

2641
export type SelectFeeLevel = Static<typeof SelectFeeLevel>;

packages/suite/src/components/wallet/Fees/CustomFee.tsx

+63-17
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,14 @@ import { useSelector, useTranslation } from 'src/hooks/suite';
3535
import { selectLanguage } from 'src/reducers/suite/suiteReducer';
3636
import { validateDecimals } from 'src/utils/suite/validation';
3737

38-
import { BorderTopWrapper } from './Fees';
3938
import { InputError } from '../InputError';
4039

4140
const FEE_PER_UNIT = 'feePerUnit';
4241
const FEE_LIMIT = 'feeLimit';
4342

43+
const MAX_FEE_PER_GAS = 'maxFeePerGas';
44+
const MAX_PRIORITY_FEE_PER_GAS = 'maxPriorityFeePerGas';
45+
4446
interface CustomFeeProps<TFieldValues extends FormState> {
4547
networkType: NetworkType;
4648
feeInfo: FeeInfo;
@@ -50,6 +52,7 @@ interface CustomFeeProps<TFieldValues extends FormState> {
5052
setValue: UseFormSetValue<TFieldValues>;
5153
getValues: UseFormGetValues<TFieldValues>;
5254
composedFeePerByte: string;
55+
shouldUsePriorityFees?: boolean;
5356
}
5457

5558
const getAverageFee = (levels: FeeLevel[]) => `${levels[levels.length > 2 ? 1 : 0].feePerUnit}`;
@@ -60,13 +63,16 @@ export const CustomFee = <TFieldValues extends FormState>({
6063
register,
6164
control,
6265
composedFeePerByte,
66+
shouldUsePriorityFees = false,
6367
...props
6468
}: CustomFeeProps<TFieldValues>) => {
6569
const { translationString } = useTranslation();
6670
const isBelowLaptop = useMediaQuery(`(max-width: ${variables.SCREEN_SIZE.LG})`);
6771

6872
const locale = useSelector(selectLanguage);
6973

74+
console.log('feeInfo', feeInfo);
75+
7076
// Type assertion allowing to make the component reusable, see https://stackoverflow.com/a/73624072.
7177
const { getValues, setValue } = props as unknown as UseFormReturn<FormState>;
7278
const errors = props.errors as unknown as FieldErrors<FormState>;
@@ -77,9 +83,13 @@ export const CustomFee = <TFieldValues extends FormState>({
7783
const feeUnits = getFeeUnits(networkType);
7884
const estimatedFeeLimit = getValues('estimatedFeeLimit');
7985

86+
// const maxFeePerGas = shouldUsePriorityFees ? getValues(MAX_FEE_PER_GAS) : undefined; //only for priority fees on evms
87+
// const maxPriorityFeePerGas = shouldUsePriorityFees
88+
// ? getValues(MAX_PRIORITY_FEE_PER_GAS)
89+
// : undefined;
90+
8091
const feePerUnitError = errors.feePerUnit;
8192
const feeLimitError = errors.feeLimit;
82-
const { elevation } = useElevation();
8393

8494
const useFeeLimit = networkType === 'ethereum';
8595
const isComposedFeeRateDifferent =
@@ -219,21 +229,57 @@ export const CustomFee = <TFieldValues extends FormState>({
219229
) : (
220230
<input type="hidden" {...register(FEE_LIMIT as FieldPath<TFieldValues>)} />
221231
)}
222-
<NumberInput
223-
label={useFeeLimit ? <Translation id="TR_GAS_PRICE" /> : undefined}
224-
locale={locale}
225-
control={control}
226-
inputState={getInputState(feePerUnitError)}
227-
innerAddon={
228-
<Text variant="tertiary" typographyStyle="label">
229-
{feeUnits}
230-
</Text>
231-
}
232-
name={FEE_PER_UNIT}
233-
data-testid={FEE_PER_UNIT}
234-
rules={feeRules}
235-
bottomText={feePerUnitError?.message || null}
236-
/>
232+
233+
{shouldUsePriorityFees && feeInfo.levels[0].ethFeeType === 'eip1559' ? (
234+
<>
235+
<NumberInput
236+
label={<Translation id="TR_MAX_PRIORITY_FEE_PER_GAS" />}
237+
locale={locale}
238+
control={control}
239+
inputState={getInputState(feePerUnitError)}
240+
innerAddon={
241+
<Text variant="tertiary" typographyStyle="label">
242+
{feeUnits}
243+
</Text>
244+
}
245+
name={MAX_PRIORITY_FEE_PER_GAS}
246+
data-testid={MAX_PRIORITY_FEE_PER_GAS}
247+
rules={feeRules}
248+
bottomText={feePerUnitError?.message || null}
249+
/>
250+
<NumberInput
251+
label={<Translation id="TR_MAX_FEE_PER_GAS" />}
252+
locale={locale}
253+
control={control}
254+
inputState={getInputState(feePerUnitError)}
255+
innerAddon={
256+
<Text variant="tertiary" typographyStyle="label">
257+
{feeUnits}
258+
</Text>
259+
}
260+
name={MAX_FEE_PER_GAS}
261+
data-testid={MAX_FEE_PER_GAS}
262+
rules={feeRules}
263+
bottomText={feePerUnitError?.message || null}
264+
/>
265+
</>
266+
) : (
267+
<NumberInput
268+
label={useFeeLimit ? <Translation id="TR_GAS_PRICE" /> : undefined}
269+
locale={locale}
270+
control={control}
271+
inputState={getInputState(feePerUnitError)}
272+
innerAddon={
273+
<Text variant="tertiary" typographyStyle="label">
274+
{feeUnits}
275+
</Text>
276+
}
277+
name={FEE_PER_UNIT}
278+
data-testid={FEE_PER_UNIT}
279+
rules={feeRules}
280+
bottomText={feePerUnitError?.message || null}
281+
/>
282+
)}
237283
</Grid>
238284
{feeDifferenceWarning && <Note>{feeDifferenceWarning}</Note>}
239285
</Column>

0 commit comments

Comments
 (0)