Skip to content

Commit

Permalink
feat(suite): build priority fees levels
Browse files Browse the repository at this point in the history
  • Loading branch information
enjojoy committed Jan 16, 2025
1 parent df8de3c commit dc86dbe
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 17 deletions.
21 changes: 21 additions & 0 deletions packages/blockchain-link-types/src/responses.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,27 @@ export interface EstimateFee {
feePerUnit: string;
feePerTx?: string;
feeLimit?: string;
eip1559?: {
baseFeePerGas: string;
low: {
maxFeePerGas: string;
maxPriorityFeePerGas: string;
minWaitTimeEstimate: number;
maxWaitTimeEstimate: number;
};
medium: {
maxFeePerGas: string;
maxPriorityFeePerGas: string;
minWaitTimeEstimate: number;
maxWaitTimeEstimate: number;
};
high: {
maxFeePerGas: string;
maxPriorityFeePerGas: string;
minWaitTimeEstimate: number;
maxWaitTimeEstimate: number;
};
};
}[];
}

Expand Down
53 changes: 41 additions & 12 deletions packages/connect/src/api/bitcoin/Fees.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,19 +82,48 @@ export class FeeLevels {
async loadMisc(blockchain: Blockchain) {
try {
const [response] = await blockchain.estimateFee({ blocks: [1] });

if (response.eip1559) {
const eip1559LevelKeys = ['low', 'medium', 'high'] as const;

const { eip1559, ...baseLevel } = response;
const eip1559Levels = eip1559LevelKeys.map(levelKey => {
const level = eip1559[levelKey];

return {
label: levelKey,
baseFeePerGas: eip1559.baseFeePerGas,
maxFeePerGas: level.maxFeePerGas,
maxPriorityFeePerGas: level.maxPriorityFeePerGas,
minWaitTimeEstimate: level.minWaitTimeEstimate,
maxWaitTimeEstimate: level.maxWaitTimeEstimate,
feePerUnit: '0',
feeLimit: undefined,
ethFeeType: 'eip1559' as const,
blocks: -1,
};
});

this.levels = [
{ ...baseLevel, label: 'normal' as const, blocks: -1, ethFeeType: 'legacy' },
...eip1559Levels,
];
} else {
this.levels[0] = {
...this.levels[0],
...response,
// validate `feePerUnit` from the backend
// should be lower than `coinInfo.maxFee` and higher than `coinInfo.minFee`
// xrp sends values from 1 to very high number occasionally
// see: https://github.com/trezor/trezor-suite/blob/develop/packages/blockchain-link/src/workers/ripple/index.ts#L316
feePerUnit: Math.min(
this.coinInfo.maxFee,
Math.max(this.coinInfo.minFee, parseInt(response.feePerUnit, 10)),
).toString(),
};
}

// misc coins should have only one FeeLevel (normal)
this.levels[0] = {
...this.levels[0],
...response,
// validate `feePerUnit` from the backend
// should be lower than `coinInfo.maxFee` and higher than `coinInfo.minFee`
// xrp sends values from 1 to very high number occasionally
// see: https://github.com/trezor/trezor-suite/blob/develop/packages/blockchain-link/src/workers/ripple/index.ts#L316
feePerUnit: Math.min(
this.coinInfo.maxFee,
Math.max(this.coinInfo.minFee, parseInt(response.feePerUnit, 10)),
).toString(),
};
} catch {
// silent
}
Expand Down
15 changes: 15 additions & 0 deletions packages/connect/src/types/fees.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,14 @@ export const FeeInfo = Type.Object({
dustLimit: Type.Number(),
});

export type PriorityFeeEstimationDetails = Static<typeof PriorityFeeEstimationDetails>;
export const PriorityFeeEstimationDetails = Type.Object({
maxFeePerGas: Type.String(),
maxPriorityFeePerGas: Type.String(),
maxWaitTimeEstimate: Type.Number(),
minWaitTimeEstimate: Type.Number(),
});

export type FeeLevel = Static<typeof FeeLevel>;
export const FeeLevel = Type.Object({
label: Type.Union([
Expand All @@ -16,11 +24,18 @@ export const FeeLevel = Type.Object({
Type.Literal('economy'),
Type.Literal('low'),
Type.Literal('custom'),
Type.Literal('medium'),
]),
ethFeeType: Type.Optional(Type.Union([Type.Literal('legacy'), Type.Literal('eip1559')])),
feePerUnit: Type.String(),
blocks: Type.Number(),
feeLimit: Type.Optional(Type.String()), // eth gas limit
feePerTx: Type.Optional(Type.String()), // fee for BlockchainEstimateFeeParams.request.specific
baseFeePerGas: Type.Optional(Type.String()),
maxFeePerGas: Type.Optional(Type.String()),
maxPriorityFeePerGas: Type.Optional(Type.String()),
maxWaitTimeEstimate: Type.Optional(Type.Number()),
minWaitTimeEstimate: Type.Optional(Type.Number()),
});

export type SelectFeeLevel = Static<typeof SelectFeeLevel>;
Expand Down
8 changes: 3 additions & 5 deletions suite-common/wallet-core/src/blockchain/blockchainThunks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ const getAccountSyncInterval = (symbol: NetworkSymbol) =>

// sort FeeLevels in reversed order (Low > High)
// TODO: consider to use same order in @trezor/connect to avoid double sorting
const order: FeeLevel['label'][] = ['low', 'economy', 'normal', 'high'];
const order: FeeLevel['label'][] = ['low', 'economy', 'medium', 'normal', 'high'];
const sortLevels = (levels: FeeLevel[]) =>
levels.sort((levelA, levelB) => order.indexOf(levelA.label) - order.indexOf(levelB.label));

Expand Down Expand Up @@ -124,13 +124,11 @@ export const updateFeeInfoThunk = createThunk(
let newFeeInfo;

if (network.networkType === 'ethereum') {
// NOTE: ethereum smart fees are not implemented properly in @trezor/connect Issue: https://github.com/trezor/trezor-suite/issues/5340
// create raw call to @trezor/blockchain-link, receive data and create FeeLevel.normal from it

const result = await TrezorConnect.blockchainEstimateFee({
coin: network.symbol,
request: {
blocks: [2],
feeLevels: 'smart',
specific: {
from: '0x0000000000000000000000000000000000000000',
to: '0x0000000000000000000000000000000000000000',
Expand All @@ -143,7 +141,7 @@ export const updateFeeInfoThunk = createThunk(
levels: result.payload.levels.map(l => ({
...l,
blocks: -1, // NOTE: @trezor/connect returns -1 for ethereum default
label: 'normal' as const,
label: l.label || ('normal' as const),
})),
};
}
Expand Down

0 comments on commit dc86dbe

Please sign in to comment.