Skip to content

Commit 6645345

Browse files
committed
chore(suite): wip
1 parent 9dfb6d1 commit 6645345

File tree

17 files changed

+262
-82
lines changed

17 files changed

+262
-82
lines changed

packages/connect/src/api/ethereum/EthereumFees.ts

+1-19
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { BigNumber } from '@trezor/utils/src/bigNumber';
22

33
import { Blockchain } from '../../backend/BlockchainLink';
44
import type { EthereumNetworkInfo, FeeLevel } from '../../types';
5-
import { Blocks, MiscFeeLevels, findBlocksForFee } from '../common/MiscFees';
5+
import { Blocks, MiscFeeLevels } from '../common/MiscFees';
66

77
type EipResponse1559Level = 'low' | 'medium' | 'high';
88
type Eip1559Level = 'low' | 'normal' | 'high';
@@ -72,22 +72,4 @@ export class EthereumFeeLevels extends MiscFeeLevels {
7272

7373
return this.levels;
7474
}
75-
76-
updateEthereumCustomFee(
77-
feePerUnit: string,
78-
effectiveGasPrice?: string,
79-
maxPriorityFeePerGas?: string,
80-
) {
81-
// remove "custom" level from list
82-
this.levels = this.levels.filter(l => l.label !== 'custom');
83-
// recreate "custom" level
84-
const blocks = findBlocksForFee(feePerUnit, this.blocks);
85-
this.levels.push({
86-
label: 'custom',
87-
feePerUnit,
88-
blocks,
89-
maxPriorityFeePerGas,
90-
effectiveGasPrice,
91-
});
92-
}
9375
}

packages/connect/src/types/fees.ts

+2-8
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,6 @@ 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.Optional(Type.Number()),
16-
minWaitTimeEstimate: Type.Optional(Type.Number()),
17-
});
18-
1911
export type FeeLevel = Static<typeof FeeLevel>;
2012
export const FeeLevel = Type.Object({
2113
label: Type.Union([
@@ -32,6 +24,8 @@ export const FeeLevel = Type.Object({
3224
baseFeePerGas: Type.Optional(Type.String()),
3325
maxFeePerGas: Type.Optional(Type.String()),
3426
effectiveGasPrice: Type.Optional(Type.String()),
27+
customMaxBaseFeePerGas: Type.Optional(Type.String()),
28+
customMaxPriorityFeePerGas: Type.Optional(Type.String()),
3529
maxPriorityFeePerGas: Type.Optional(Type.String()),
3630
maxWaitTimeEstimate: Type.Optional(Type.Number()),
3731
minWaitTimeEstimate: Type.Optional(Type.Number()),

packages/suite/src/actions/wallet/stake/stakeFormActions.ts

+5
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ export const calculate = (
8181
max,
8282
fee: feeInBaseUnits,
8383
feePerByte: feeLevel.feePerUnit,
84+
maxFeePerGas: feeLevel.effectiveGasPrice || undefined,
85+
maxPriorityFeePerGas: feeLevel.maxPriorityFeePerGas || undefined,
8486
feeLimit: feeLevel.feeLimit,
8587
bytes: 0,
8688
inputs: [],
@@ -123,6 +125,7 @@ export const composeStakingTransaction = (
123125
) => {
124126
const { account, network } = formState;
125127
const composeOutputs = getExternalComposeOutput(formValues, account, network);
128+
console.log('composeOutputs', formValues, composeOutputs);
126129
if (!composeOutputs) return; // no valid Output
127130

128131
const { output, decimals } = composeOutputs;
@@ -131,6 +134,8 @@ export const composeStakingTransaction = (
131134
// wrap response into PrecomposedLevels object where key is a FeeLevel label
132135
const wrappedResponse: PrecomposedLevels = {};
133136
const compareWithAmount = formValues.stakeType === 'stake';
137+
138+
console.log('predefinedLevels', predefinedLevels);
134139
const response = predefinedLevels.map(level =>
135140
calculateTransaction(
136141
availableBalance,

packages/suite/src/actions/wallet/stake/stakeFormEthereumActions.ts

+26-4
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,15 @@ import {
99
UNSTAKE_INTERCHANGES,
1010
} from '@suite-common/wallet-constants';
1111
import { ComposeActionContext, selectSelectedDevice } from '@suite-common/wallet-core';
12+
import { calculateEffectiveGasPrice } from '@suite-common/wallet-core/src/send/sendFormEthereumUtils';
1213
import {
1314
AddressDisplayOptions,
1415
ExternalOutput,
1516
PrecomposedTransaction,
1617
PrecomposedTransactionFinal,
1718
StakeFormState,
1819
} from '@suite-common/wallet-types';
19-
import { calculateEthFee, getAccountIdentity, isPending } from '@suite-common/wallet-utils';
20+
import { calculateMaxEthFee, getAccountIdentity, isPending } from '@suite-common/wallet-utils';
2021
import TrezorConnect, { FeeLevel } from '@trezor/connect';
2122
import { BigNumber } from '@trezor/utils/src/bigNumber';
2223

@@ -31,14 +32,18 @@ import {
3132

3233
import { calculate, composeStakingTransaction } from './stakeFormActions';
3334

34-
const calculateTransaction = (
35+
const calculateStakingTransaction = (
3536
availableBalance: string,
3637
output: ExternalOutput,
3738
feeLevel: FeeLevel,
3839
compareWithAmount = true,
3940
symbol: NetworkSymbol,
4041
): PrecomposedTransaction => {
41-
const feeInWei = calculateEthFee(toWei(feeLevel.feePerUnit, 'gwei'), feeLevel.feeLimit || '0');
42+
const isEip1559 = feeLevel.maxPriorityFeePerGas !== undefined;
43+
44+
const feeInWei = isEip1559
45+
? calculateMaxEthFee(feeLevel.effectiveGasPrice, feeLevel.feeLimit)
46+
: calculateMaxEthFee(toWei(feeLevel.feePerUnit, 'gwei'), feeLevel.feeLimit);
4247

4348
const stakingParams = {
4449
feeInBaseUnits: feeInWei,
@@ -47,6 +52,8 @@ const calculateTransaction = (
4752
minAmountForWithdrawalInBaseUnits: toWei(MIN_ETH_FOR_WITHDRAWALS.toString(), 'ether'),
4853
};
4954

55+
console.log('feeLevel', feeLevel);
56+
5057
return calculate(availableBalance, output, feeLevel, compareWithAmount, symbol, stakingParams);
5158
};
5259

@@ -81,11 +88,20 @@ export const composeTransaction =
8188
predefinedLevels.forEach(l => (l.feeLimit = customFeeLimit));
8289
}
8390
// in case when selectedFee is set to 'custom' construct this FeeLevel from values
91+
//TODO: calculate effective gas price here?
8492
if (formValues.selectedFee === 'custom') {
93+
const calculatedEffectiveGasPrice = calculateEffectiveGasPrice(
94+
formValues.customMaxPriorityFeePerGas,
95+
formValues.customMaxBaseFeePerGas,
96+
);
8597
predefinedLevels.push({
8698
label: 'custom',
8799
feePerUnit: formValues.feePerUnit,
88100
feeLimit: formValues.feeLimit,
101+
customMaxBaseFeePerGas: formValues.customMaxBaseFeePerGas,
102+
customMaxPriorityFeePerGas: formValues.customMaxPriorityFeePerGas,
103+
effectiveGasPrice: calculatedEffectiveGasPrice,
104+
maxPriorityFeePerGas: toWei(Number(formValues.customMaxPriorityFeePerGas), 'gwei'),
89105
blocks: -1,
90106
});
91107
}
@@ -94,7 +110,7 @@ export const composeTransaction =
94110
formValues,
95111
formState,
96112
predefinedLevels,
97-
calculateTransaction,
113+
calculateStakingTransaction,
98114
undefined,
99115
customFeeLimit,
100116
);
@@ -150,6 +166,8 @@ export const signTransaction =
150166
identity,
151167
amount: formValues.outputs[0].amount,
152168
gasPrice: transactionInfo.feePerByte,
169+
maxFeePerGas: transactionInfo.maxFeePerGas,
170+
maxPriorityFeePerGas: transactionInfo.maxPriorityFeePerGas,
153171
nonce,
154172
chainId: network.chainId,
155173
});
@@ -161,6 +179,8 @@ export const signTransaction =
161179
identity,
162180
amount: formValues.outputs[0].amount,
163181
gasPrice: transactionInfo.feePerByte,
182+
maxFeePerGas: transactionInfo.maxFeePerGas,
183+
maxPriorityFeePerGas: transactionInfo.maxPriorityFeePerGas,
164184
nonce,
165185
chainId: network.chainId,
166186
interchanges: UNSTAKE_INTERCHANGES,
@@ -172,6 +192,8 @@ export const signTransaction =
172192
from: account.descriptor,
173193
identity,
174194
gasPrice: transactionInfo.feePerByte,
195+
maxFeePerGas: transactionInfo.maxFeePerGas,
196+
maxPriorityFeePerGas: transactionInfo.maxPriorityFeePerGas,
175197
nonce,
176198
chainId: network.chainId,
177199
});

packages/suite/src/components/suite/modals/ReduxModal/TransactionReviewModal/TransactionReviewSummary.tsx

+20-14
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { formatDurationStrict } from '@suite-common/suite-utils';
2-
import { NetworkType, networks } from '@suite-common/wallet-config';
2+
import { NetworkType, getNetworkFeatures, networks } from '@suite-common/wallet-config';
33
import { FeeInfo, GeneralPrecomposedTransactionFinal, StakeType } from '@suite-common/wallet-types';
44
import { getFee } from '@suite-common/wallet-utils';
55
import { Box, IconButton, Note, Row, Text } from '@trezor/components';
@@ -47,14 +47,22 @@ export const TransactionReviewSummary = ({
4747
const fees = useSelector(state => state.wallet.fees);
4848
const locale = useLocales();
4949
const { symbol, accountType, index, networkType } = account;
50+
5051
const network = networks[symbol];
51-
const fee = getFee(networkType, tx);
52+
53+
const baseFee = fees[symbol].levels[0].baseFeePerGas;
54+
const hasEip1559Feature = getNetworkFeatures(symbol).includes('eip1559');
55+
const shouldUsePriorityFees = !!tx.fee && hasEip1559Feature && !!baseFee;
56+
const fee = getFee({ account, tx, shouldUsePriorityFees });
57+
5258
const estimateTime = getEstimatedTime(networkType, fees[account.symbol], tx);
5359

5460
const formFeeRate = drafts[currentAccountKey]?.feePerUnit;
5561
const isFeeCustom = drafts[currentAccountKey]?.selectedFee === 'custom';
5662
const isComposedFeeRateDifferent = isFeeCustom && formFeeRate !== fee;
5763

64+
const isEthereumNetworkType = networkType === 'ethereum';
65+
5866
return (
5967
<Row columnGap={spacings.md} rowGap={spacings.xxs} flexWrap="wrap">
6068
<Row gap={spacings.xxs}>
@@ -74,25 +82,23 @@ export const TransactionReviewSummary = ({
7482
</Note>
7583
)}
7684

77-
{!!tx.feeLimit && network.networkType !== 'solana' && (
85+
{!!tx.feeLimit && network.networkType !== 'solana' && !hasEip1559Feature && (
7886
<Note iconName="gasPump">
7987
<Translation id="TR_GAS_LIMIT" />
8088
{': '}
8189
{tx.feeLimit}
8290
</Note>
8391
)}
8492

85-
{networkType === 'ethereum' ? (
86-
<Note iconName="gasPump">
87-
<Translation id="TR_GAS_PRICE" />
88-
{': '}
89-
<FeeRate feeRate={fee} networkType={network.networkType} symbol={symbol} />
90-
</Note>
91-
) : (
92-
<Note iconName="receipt">
93-
<FeeRate feeRate={fee} networkType={network.networkType} symbol={symbol} />
94-
</Note>
95-
)}
93+
<Note iconName={isEthereumNetworkType ? 'gasPump' : 'receipt'}>
94+
{isEthereumNetworkType && (
95+
<>
96+
<Translation id="TR_GAS_PRICE" />
97+
{': '}
98+
</>
99+
)}
100+
<FeeRate feeRate={fee} networkType={network.networkType} symbol={symbol} />
101+
</Note>
96102

97103
{isComposedFeeRateDifferent && network.networkType === 'bitcoin' && (
98104
<Translation id="TR_FEE_RATE_CHANGED" />

packages/suite/src/hooks/wallet/form/useStakeCompose.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -184,9 +184,12 @@ export const useStakeCompose = <TFieldValues extends StakeFormState>({
184184
setValue('selectedFee', nearest);
185185
if (nearest === 'custom') {
186186
// @ts-expect-error: type = error already filtered above
187-
const { feePerByte, feeLimit } = composed;
187+
const { feePerByte, feeLimit, effectiveGasPrice, maxPriorityFeePerGas } =
188+
composed;
188189
setValue('feePerUnit', feePerByte);
189190
setValue('feeLimit', feeLimit || '');
191+
setValue('customMaxPriorityFeePerGas', maxPriorityFeePerGas || '');
192+
setValue('customMaxBaseFeePerGas', effectiveGasPrice || '');
190193
}
191194
}
192195
// or do nothing, use default composed tx

packages/suite/src/hooks/wallet/useTradingRecomposeAndSign.ts

+7
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,10 @@ export const useTradingRecomposeAndSign = () => {
7070
setMaxOutputId: !composed.token?.contract ? setMaxOutputId : undefined,
7171
selectedFee,
7272
feePerUnit: composed.feePerByte,
73+
maxFeePerGas: composed.maxFeePerGas,
74+
maxPriorityFeePerGas: composed.maxPriorityFeePerGas,
75+
customMaxBaseFeePerGas: composed.maxFeePerGas,
76+
customMaxPriorityFeePerGas: composed.maxPriorityFeePerGas,
7377
feeLimit: composed.feeLimit || '',
7478
estimatedFeeLimit: composed.estimatedFeeLimit,
7579
options,
@@ -85,6 +89,8 @@ export const useTradingRecomposeAndSign = () => {
8589
networkType: account.networkType,
8690
feeInfo: fees[account.symbol],
8791
});
92+
93+
console.log('feeInfo', feeInfo, formState);
8894
const composeContext = { account, network, feeInfo };
8995

9096
// recalcCustomLimit is used in case of custom fee level, when we want to keep the feePerUnit defined by the user
@@ -124,6 +130,7 @@ export const useTradingRecomposeAndSign = () => {
124130

125131
return;
126132
}
133+
//TODO priority
127134
formState.feeLimit = normalLevels.normal.feeLimit;
128135
}
129136

packages/suite/src/reducers/wallet/tradingReducer.ts

+8-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,14 @@ import { Action } from 'src/types/suite';
3636
export interface ComposedTransactionInfo {
3737
composed?: Pick<
3838
PrecomposedTransactionFinal,
39-
'feePerByte' | 'estimatedFeeLimit' | 'feeLimit' | 'token' | 'fee'
39+
| 'feePerByte'
40+
| 'estimatedFeeLimit'
41+
| 'feeLimit'
42+
| 'token'
43+
| 'fee'
44+
| 'maxFeePerGas'
45+
| 'maxPriorityFeePerGas'
46+
| 'effectiveGasPrice'
4047
>;
4148
selectedFee?: FeeLevel['label'];
4249
}

packages/suite/src/support/messages.ts

+32
Original file line numberDiff line numberDiff line change
@@ -3444,6 +3444,18 @@ export default defineMessages({
34443444
id: 'TR_CURRENT_FEE_CUSTOM_FEES',
34453445
defaultMessage: 'Current network fee:',
34463446
},
3447+
TR_CURRENT_BASE_FEE: {
3448+
id: 'TR_CURRENT_BASE_FEE',
3449+
defaultMessage: 'Current network base fee:',
3450+
},
3451+
TR_MAX_BASE_FEE_PER_GAS: {
3452+
id: 'TR_MAX_BASE_FEE_PER_GAS',
3453+
defaultMessage: 'Max base fee',
3454+
},
3455+
TR_CUSTOM_MAX_BASE_FEE_USE_NETWORK_BASE_FEE: {
3456+
id: 'TR_CUSTOM_MAX_BASE_FEE_USE_NETWORK_BASE_FEE',
3457+
defaultMessage: 'Use network base fee',
3458+
},
34473459
GAS_LIMIT_IS_NOT_SET: {
34483460
id: 'GAS_LIMIT_IS_NOT_SET',
34493461
defaultMessage: 'Set gas limit for this transaction',
@@ -5593,6 +5605,10 @@ export default defineMessages({
55935605
description: 'Label in Send form for Ethereum network type',
55945606
id: 'MAX_FEE',
55955607
},
5608+
WHY_FEES: {
5609+
defaultMessage: 'Why fees?',
5610+
id: 'WHY_FEES',
5611+
},
55965612
EXPECTED_FEE: {
55975613
defaultMessage: 'Expected fee',
55985614
description: 'Label in Send form for Solana network type',
@@ -5618,6 +5634,18 @@ export default defineMessages({
56185634
defaultMessage: 'Low',
56195635
id: 'FEE_LEVEL_LOW',
56205636
},
5637+
FEE_LEVEL_MEDIUM: {
5638+
defaultMessage: 'Medium',
5639+
id: 'FEE_LEVEL_MEDIUM',
5640+
},
5641+
TR_MAX_PRIORITY_FEE_PER_GAS: {
5642+
defaultMessage: 'Priority fee',
5643+
id: 'TR_MAX_PRIORITY_FEE_PER_GAS',
5644+
},
5645+
TR_MAX_FEE_PER_GAS: {
5646+
defaultMessage: 'Max fee',
5647+
id: 'TR_MAX_FEE_PER_GAS',
5648+
},
56215649
CUSTOM_FEE_IS_NOT_SET: {
56225650
defaultMessage:
56235651
'Enter the fee rate you want to spend in order to complete this transaction.',
@@ -5631,6 +5659,10 @@ export default defineMessages({
56315659
defaultMessage: 'Enter a fee between {minFee} and {maxFee}',
56325660
id: 'CUSTOM_FEE_NOT_IN_RANGE',
56335661
},
5662+
TR_CUSTOM_FEE_BASE_FEE_BELOW_CURRENT: {
5663+
defaultMessage: 'Custom base fee can not be below current network base fee.',
5664+
id: 'TR_CUSTOM_FEE_BASE_FEE_BELOW_CURRENT',
5665+
},
56345666
CUSTOM_FEE_LIMIT_BELOW_RECOMMENDED: {
56355667
defaultMessage: 'Gas limit too low',
56365668
id: 'CUSTOM_FEE_LIMIT_BELOW_RECOMMENDED',

packages/suite/src/utils/suite/__tests__/ethereumStaking.test.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,12 @@ import {
5656
describe('transformTx', () => {
5757
transformTxFixtures.forEach(test => {
5858
it(test.description, () => {
59-
const result = transformTx(test.tx, test.gasPrice, test.nonce, test.chainId);
59+
const result = transformTx({
60+
tx: test.tx,
61+
gasPrice: test.gasPrice,
62+
nonce: test.nonce,
63+
chainId: test.chainId,
64+
});
6065
expect(result).toEqual(test.result);
6166
expect(result).not.toHaveProperty('from');
6267
});

0 commit comments

Comments
 (0)