From dfed08aca714e5858c2a8f3fb5b87ae6872ef6f2 Mon Sep 17 00:00:00 2001 From: Elliot Winkler Date: Mon, 21 Mar 2022 12:35:03 -0600 Subject: [PATCH 1/2] Backfill tests for `gas-util` to raise coverage Recent changes to `gas-util` lowered test coverage, forcing exclusion from the Jest coverage report. These changes allow us to include this file again by raising coverage. --- src/gas/gas-util.test.ts | 855 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 798 insertions(+), 57 deletions(-) diff --git a/src/gas/gas-util.test.ts b/src/gas/gas-util.test.ts index 28ab1fea472..ce25be41602 100644 --- a/src/gas/gas-util.test.ts +++ b/src/gas/gas-util.test.ts @@ -1,8 +1,12 @@ import nock from 'nock'; +import { toHex } from '../util'; +import { GasFeeEstimates } from './GasFeeController'; import { fetchLegacyGasPriceEstimates, normalizeGWEIDecimalNumbers, fetchGasEstimates, + fetchEthGasPriceEstimate, + calculateTimeEstimate, } from './gas-util'; const mockEIP1559ApiResponses = [ @@ -50,7 +54,75 @@ const mockEIP1559ApiResponses = [ }, ]; -describe('gas utils', () => { +describe('gas-util', () => { + describe('normalizeGWEIDecimalNumbers', () => { + describe('given a number', () => { + it('should return a whole number as a string if no normalization is needed', () => { + expect(normalizeGWEIDecimalNumbers(1)).toBe('1'); + expect(normalizeGWEIDecimalNumbers(123)).toBe('123'); + expect(normalizeGWEIDecimalNumbers(101)).toBe('101'); + expect(normalizeGWEIDecimalNumbers(1234)).toBe('1234'); + expect(normalizeGWEIDecimalNumbers(1000)).toBe('1000'); + }); + + it('should return a decimal number greater than 1 as a string if no normalization is needed', () => { + expect(normalizeGWEIDecimalNumbers(1.1)).toBe('1.1'); + expect(normalizeGWEIDecimalNumbers(123.01)).toBe('123.01'); + expect(normalizeGWEIDecimalNumbers(101.001)).toBe('101.001'); + expect(normalizeGWEIDecimalNumbers(100.001)).toBe('100.001'); + expect(normalizeGWEIDecimalNumbers(1234.567)).toBe('1234.567'); + }); + + it('should return a decimal number less than 1 as a string if no normalization is needed', () => { + expect(normalizeGWEIDecimalNumbers(0.1)).toBe('0.1'); + expect(normalizeGWEIDecimalNumbers(0.01)).toBe('0.01'); + expect(normalizeGWEIDecimalNumbers(0.001)).toBe('0.001'); + expect(normalizeGWEIDecimalNumbers(0.567)).toBe('0.567'); + }); + + it('should round a decimal number to 9 places before converting to a string', () => { + expect(normalizeGWEIDecimalNumbers(1.0000000162)).toBe('1.000000016'); + expect(normalizeGWEIDecimalNumbers(1.0000000165)).toBe('1.000000017'); + expect(normalizeGWEIDecimalNumbers(1.0000000199)).toBe('1.00000002'); + expect(normalizeGWEIDecimalNumbers(1.9999999999)).toBe('2'); + expect(normalizeGWEIDecimalNumbers(1.0000005998)).toBe('1.0000006'); + expect(normalizeGWEIDecimalNumbers(123456.0000005998)).toBe( + '123456.0000006', + ); + expect(normalizeGWEIDecimalNumbers(1.000000016025)).toBe('1.000000016'); + expect(normalizeGWEIDecimalNumbers(1.0000000160000028)).toBe( + '1.000000016', + ); + expect(normalizeGWEIDecimalNumbers(1.000000016522)).toBe('1.000000017'); + expect(normalizeGWEIDecimalNumbers(1.000000016800022)).toBe( + '1.000000017', + ); + }); + + it('should convert NaN to 0', () => { + expect(normalizeGWEIDecimalNumbers(NaN)).toBe('0'); + }); + }); + + describe('given a string', () => { + it('should remove trailing zeroes', () => { + expect(normalizeGWEIDecimalNumbers('0.5000')).toBe('0.5'); + expect(normalizeGWEIDecimalNumbers('123.002300')).toBe('123.0023'); + expect(normalizeGWEIDecimalNumbers('123.002300000000')).toBe( + '123.0023', + ); + expect(normalizeGWEIDecimalNumbers('0.00000200000')).toBe('0.000002'); + }); + + it('should add leading zeroes if necessary', () => { + expect(normalizeGWEIDecimalNumbers('.1')).toBe('0.1'); + expect(normalizeGWEIDecimalNumbers('.01')).toBe('0.01'); + expect(normalizeGWEIDecimalNumbers('.001')).toBe('0.001'); + expect(normalizeGWEIDecimalNumbers('.567')).toBe('0.567'); + }); + }); + }); + describe('fetchGasEstimates', () => { it('should fetch external gasFeeEstimates when data is valid', async () => { const scope = nock('https://not-a-real-url/') @@ -155,72 +227,741 @@ describe('gas utils', () => { }); }); - describe('normalizeGWEIDecimalNumbers', () => { - it('should convert a whole number to WEI', () => { - expect(normalizeGWEIDecimalNumbers(1)).toBe('1'); - expect(normalizeGWEIDecimalNumbers(123)).toBe('123'); - expect(normalizeGWEIDecimalNumbers(101)).toBe('101'); - expect(normalizeGWEIDecimalNumbers(1234)).toBe('1234'); - expect(normalizeGWEIDecimalNumbers(1000)).toBe('1000'); - }); + describe('fetchEthGasPriceEstimate', () => { + it('should fetch the current gas price and returns it as GWEI within an object', async () => { + const ethQuery = { + gasPrice(callback: any) { + callback(null, toHex('150340000000')); + }, + }; - it('should convert a number with a decimal part to WEI', () => { - expect(normalizeGWEIDecimalNumbers(1.1)).toBe('1.1'); - expect(normalizeGWEIDecimalNumbers(123.01)).toBe('123.01'); - expect(normalizeGWEIDecimalNumbers(101.001)).toBe('101.001'); - expect(normalizeGWEIDecimalNumbers(100.001)).toBe('100.001'); - expect(normalizeGWEIDecimalNumbers(1234.567)).toBe('1234.567'); - }); + const estimate = await fetchEthGasPriceEstimate(ethQuery); - it('should convert a number < 1 to WEI', () => { - expect(normalizeGWEIDecimalNumbers(0.1)).toBe('0.1'); - expect(normalizeGWEIDecimalNumbers(0.01)).toBe('0.01'); - expect(normalizeGWEIDecimalNumbers(0.001)).toBe('0.001'); - expect(normalizeGWEIDecimalNumbers(0.567)).toBe('0.567'); + expect(estimate).toStrictEqual({ gasPrice: '150.34' }); }); + }); - it('should round to whole WEI numbers', () => { - expect(normalizeGWEIDecimalNumbers(0.1001)).toBe('0.1001'); - expect(normalizeGWEIDecimalNumbers(0.0109)).toBe('0.0109'); - expect(normalizeGWEIDecimalNumbers(0.0014)).toBe('0.0014'); - expect(normalizeGWEIDecimalNumbers(0.5676)).toBe('0.5676'); - }); + describe('calculateTimeEstimate', () => { + const buildGasFeeEstimates = ({ + estimatedBaseFee, + low = {}, + medium = {}, + high = {}, + }: { + estimatedBaseFee: string; + low?: { + minWaitTimeEstimate?: number; + maxWaitTimeEstimate?: number; + suggestedMaxPriorityFeePerGas?: string; + }; + medium?: { + minWaitTimeEstimate?: number; + maxWaitTimeEstimate?: number; + suggestedMaxPriorityFeePerGas?: string; + }; + high?: { + minWaitTimeEstimate?: number; + maxWaitTimeEstimate?: number; + suggestedMaxPriorityFeePerGas?: string; + }; + }): GasFeeEstimates => { + return { + low: { + minWaitTimeEstimate: 0, + maxWaitTimeEstimate: 0, + suggestedMaxPriorityFeePerGas: '0', + suggestedMaxFeePerGas: '0', + ...low, + }, + medium: { + minWaitTimeEstimate: 0, + maxWaitTimeEstimate: 0, + suggestedMaxPriorityFeePerGas: '0', + suggestedMaxFeePerGas: '0', + ...medium, + }, + high: { + minWaitTimeEstimate: 0, + maxWaitTimeEstimate: 0, + suggestedMaxPriorityFeePerGas: '0', + suggestedMaxFeePerGas: '0', + ...high, + }, + estimatedBaseFee, + historicalBaseFeeRange: null, + baseFeeTrend: null, + latestPriorityFeeRange: null, + historicalPriorityFeeRange: null, + priorityFeeTrend: null, + networkCongestion: null, + }; + }; - it('should handle inputs with more than 9 decimal places', () => { - expect(normalizeGWEIDecimalNumbers(1.0000000162)).toBe('1.000000016'); - expect(normalizeGWEIDecimalNumbers(1.0000000165)).toBe('1.000000017'); - expect(normalizeGWEIDecimalNumbers(1.0000000199)).toBe('1.00000002'); - expect(normalizeGWEIDecimalNumbers(1.9999999999)).toBe('2'); - expect(normalizeGWEIDecimalNumbers(1.0000005998)).toBe('1.0000006'); - expect(normalizeGWEIDecimalNumbers(123456.0000005998)).toBe( - '123456.0000006', - ); - expect(normalizeGWEIDecimalNumbers(1.000000016025)).toBe('1.000000016'); - expect(normalizeGWEIDecimalNumbers(1.0000000160000028)).toBe( - '1.000000016', - ); - expect(normalizeGWEIDecimalNumbers(1.000000016522)).toBe('1.000000017'); - expect(normalizeGWEIDecimalNumbers(1.000000016800022)).toBe( - '1.000000017', - ); - }); + describe('if the given priority fee is less than the given max fee minus the latest base fee', () => { + let maxPriorityFeePerGas: string; + let maxFeePerGas: string; + let estimatedBaseFee: string; + + beforeEach(() => { + maxPriorityFeePerGas = '1'; + maxFeePerGas = '102'; + estimatedBaseFee = '100'; + }); + + describe('and the given priority fee does not reach any of the suggested priority fee thresholds', () => { + it('should return no lower bound and an unknown upper bound', () => { + const timeBounds = calculateTimeEstimate( + maxPriorityFeePerGas, + maxFeePerGas, + buildGasFeeEstimates({ + estimatedBaseFee, + low: { + suggestedMaxPriorityFeePerGas: ( + Number(maxPriorityFeePerGas) + 0.5 + ).toString(), + }, + }), + ); + + expect(timeBounds).toStrictEqual({ + lowerTimeBound: null, + upperTimeBound: 'unknown', + }); + }); + }); + + describe('and the given priority fee reaches the suggested low priority fee threshold, but does reach the medium priority fee threshold', () => { + it('should return a lower and upper bound equal to the low min and max wait time', () => { + const timeBounds = calculateTimeEstimate( + maxPriorityFeePerGas, + maxFeePerGas, + buildGasFeeEstimates({ + estimatedBaseFee, + low: { + minWaitTimeEstimate: 1000, + maxWaitTimeEstimate: 2000, + suggestedMaxPriorityFeePerGas: maxPriorityFeePerGas, + }, + medium: { + suggestedMaxPriorityFeePerGas: ( + Number(maxPriorityFeePerGas) + 0.5 + ).toString(), + }, + }), + ); + + expect(timeBounds).toStrictEqual({ + lowerTimeBound: 1000, + upperTimeBound: 2000, + }); + }); + }); + + describe('and the given priority fee exceeds the suggested low priority fee threshold, but does reach the medium priority fee threshold', () => { + it('should return a lower and upper bound equal to the low min and max wait time', () => { + const timeBounds = calculateTimeEstimate( + maxPriorityFeePerGas, + maxFeePerGas, + buildGasFeeEstimates({ + estimatedBaseFee, + low: { + minWaitTimeEstimate: 1000, + maxWaitTimeEstimate: 2000, + suggestedMaxPriorityFeePerGas: ( + Number(maxPriorityFeePerGas) - 0.1 + ).toString(), + }, + medium: { + suggestedMaxPriorityFeePerGas: ( + Number(maxPriorityFeePerGas) + 0.5 + ).toString(), + }, + }), + ); + + expect(timeBounds).toStrictEqual({ + lowerTimeBound: 1000, + upperTimeBound: 2000, + }); + }); + }); + + describe('and the given priority fee reaches the suggested medium priority fee threshold, but does not cross the suggested high priority fee threshold', () => { + it('should return a lower and upper bound equal to the medium min and max wait time', () => { + const timeBounds = calculateTimeEstimate( + maxPriorityFeePerGas, + maxFeePerGas, + buildGasFeeEstimates({ + estimatedBaseFee, + low: { + suggestedMaxPriorityFeePerGas: ( + Number(maxPriorityFeePerGas) - 0.1 + ).toString(), + }, + medium: { + minWaitTimeEstimate: 1000, + maxWaitTimeEstimate: 2000, + suggestedMaxPriorityFeePerGas: maxPriorityFeePerGas, + }, + high: { + suggestedMaxPriorityFeePerGas: ( + Number(maxPriorityFeePerGas) + 0.5 + ).toString(), + }, + }), + ); + + expect(timeBounds).toStrictEqual({ + lowerTimeBound: 1000, + upperTimeBound: 2000, + }); + }); + }); + + describe('and the given priority fee exceeds the suggested medium priority fee threshold, but does not cross the suggested high priority fee threshold', () => { + it('should return a lower and upper bound equal to the medium min and max wait time', () => { + const timeBounds = calculateTimeEstimate( + maxPriorityFeePerGas, + maxFeePerGas, + buildGasFeeEstimates({ + estimatedBaseFee, + low: { + suggestedMaxPriorityFeePerGas: ( + Number(maxPriorityFeePerGas) - 0.2 + ).toString(), + }, + medium: { + minWaitTimeEstimate: 1000, + maxWaitTimeEstimate: 2000, + suggestedMaxPriorityFeePerGas: ( + Number(maxPriorityFeePerGas) - 0.1 + ).toString(), + }, + high: { + suggestedMaxPriorityFeePerGas: ( + Number(maxPriorityFeePerGas) + 0.5 + ).toString(), + }, + }), + ); + + expect(timeBounds).toStrictEqual({ + lowerTimeBound: 1000, + upperTimeBound: 2000, + }); + }); + }); + + describe('and the given priority fee reaches the suggested high priority fee threshold', () => { + it('should return a lower and upper bound equal to the high min and max wait time', () => { + const timeBounds = calculateTimeEstimate( + maxPriorityFeePerGas, + maxFeePerGas, + buildGasFeeEstimates({ + estimatedBaseFee, + low: { + suggestedMaxPriorityFeePerGas: ( + Number(maxPriorityFeePerGas) - 0.2 + ).toString(), + }, + medium: { + suggestedMaxPriorityFeePerGas: ( + Number(maxPriorityFeePerGas) - 0.1 + ).toString(), + }, + high: { + minWaitTimeEstimate: 1000, + maxWaitTimeEstimate: 2000, + suggestedMaxPriorityFeePerGas: maxPriorityFeePerGas, + }, + }), + ); + + expect(timeBounds).toStrictEqual({ + lowerTimeBound: 1000, + upperTimeBound: 2000, + }); + }); + }); - it('should work if there are extraneous trailing decimal zeroes', () => { - expect(normalizeGWEIDecimalNumbers('0.5000')).toBe('0.5'); - expect(normalizeGWEIDecimalNumbers('123.002300')).toBe('123.0023'); - expect(normalizeGWEIDecimalNumbers('123.002300000000')).toBe('123.0023'); - expect(normalizeGWEIDecimalNumbers('0.00000200000')).toBe('0.000002'); + describe('and the given priority fee exceeds the suggested high priority fee threshold', () => { + it('should return a lower bound of 0 and an upper bound equal to the high max wait time', () => { + const timeBounds = calculateTimeEstimate( + maxPriorityFeePerGas, + maxFeePerGas, + buildGasFeeEstimates({ + estimatedBaseFee, + low: { + suggestedMaxPriorityFeePerGas: ( + Number(maxPriorityFeePerGas) - 0.3 + ).toString(), + }, + medium: { + suggestedMaxPriorityFeePerGas: ( + Number(maxPriorityFeePerGas) - 0.2 + ).toString(), + }, + high: { + maxWaitTimeEstimate: 2000, + suggestedMaxPriorityFeePerGas: ( + Number(maxPriorityFeePerGas) - 0.1 + ).toString(), + }, + }), + ); + + expect(timeBounds).toStrictEqual({ + lowerTimeBound: 0, + upperTimeBound: 2000, + }); + }); + }); }); - it('should work if there is no whole number specified', () => { - expect(normalizeGWEIDecimalNumbers('.1')).toBe('0.1'); - expect(normalizeGWEIDecimalNumbers('.01')).toBe('0.01'); - expect(normalizeGWEIDecimalNumbers('.001')).toBe('0.001'); - expect(normalizeGWEIDecimalNumbers('.567')).toBe('0.567'); + describe('if the given priority fee is equal to the given max fee minus the latest base fee', () => { + let maxPriorityFeePerGas: string; + let maxFeePerGas: string; + let estimatedBaseFee: string; + + beforeEach(() => { + maxPriorityFeePerGas = '1'; + maxFeePerGas = '101'; + estimatedBaseFee = '100'; + }); + + describe('and the given priority fee does not reach any of the suggested priority fee thresholds', () => { + it('should return no lower bound and an unknown upper bound', () => { + const timeBounds = calculateTimeEstimate( + maxPriorityFeePerGas, + maxFeePerGas, + buildGasFeeEstimates({ + estimatedBaseFee, + low: { + suggestedMaxPriorityFeePerGas: ( + Number(maxPriorityFeePerGas) + 0.5 + ).toString(), + }, + }), + ); + + expect(timeBounds).toStrictEqual({ + lowerTimeBound: null, + upperTimeBound: 'unknown', + }); + }); + }); + + describe('and the given priority fee reaches the suggested low priority fee threshold, but does reach the medium priority fee threshold', () => { + it('should return a lower and upper bound equal to the low min and max wait time', () => { + const timeBounds = calculateTimeEstimate( + maxPriorityFeePerGas, + maxFeePerGas, + buildGasFeeEstimates({ + estimatedBaseFee, + low: { + minWaitTimeEstimate: 1000, + maxWaitTimeEstimate: 2000, + suggestedMaxPriorityFeePerGas: maxPriorityFeePerGas, + }, + medium: { + suggestedMaxPriorityFeePerGas: ( + Number(maxPriorityFeePerGas) + 0.5 + ).toString(), + }, + }), + ); + + expect(timeBounds).toStrictEqual({ + lowerTimeBound: 1000, + upperTimeBound: 2000, + }); + }); + }); + + describe('and the given priority fee exceeds the suggested low priority fee threshold, but does reach the medium priority fee threshold', () => { + it('should return a lower and upper bound equal to the low min and max wait time', () => { + const timeBounds = calculateTimeEstimate( + maxPriorityFeePerGas, + maxFeePerGas, + buildGasFeeEstimates({ + estimatedBaseFee, + low: { + minWaitTimeEstimate: 1000, + maxWaitTimeEstimate: 2000, + suggestedMaxPriorityFeePerGas: ( + Number(maxPriorityFeePerGas) - 0.1 + ).toString(), + }, + medium: { + suggestedMaxPriorityFeePerGas: ( + Number(maxPriorityFeePerGas) + 0.5 + ).toString(), + }, + }), + ); + + expect(timeBounds).toStrictEqual({ + lowerTimeBound: 1000, + upperTimeBound: 2000, + }); + }); + }); + + describe('and the given priority fee reaches the suggested medium priority fee threshold, but does not cross the suggested high priority fee threshold', () => { + it('should return a lower and upper bound equal to the medium min and max wait time', () => { + const timeBounds = calculateTimeEstimate( + maxPriorityFeePerGas, + maxFeePerGas, + buildGasFeeEstimates({ + estimatedBaseFee, + low: { + suggestedMaxPriorityFeePerGas: ( + Number(maxPriorityFeePerGas) - 0.1 + ).toString(), + }, + medium: { + minWaitTimeEstimate: 1000, + maxWaitTimeEstimate: 2000, + suggestedMaxPriorityFeePerGas: maxPriorityFeePerGas, + }, + high: { + suggestedMaxPriorityFeePerGas: ( + Number(maxPriorityFeePerGas) + 0.5 + ).toString(), + }, + }), + ); + + expect(timeBounds).toStrictEqual({ + lowerTimeBound: 1000, + upperTimeBound: 2000, + }); + }); + }); + + describe('and the given priority fee exceeds the suggested medium priority fee threshold, but does not cross the suggested high priority fee threshold', () => { + it('should return a lower and upper bound equal to the medium min and max wait time', () => { + const timeBounds = calculateTimeEstimate( + maxPriorityFeePerGas, + maxFeePerGas, + buildGasFeeEstimates({ + estimatedBaseFee, + low: { + suggestedMaxPriorityFeePerGas: ( + Number(maxPriorityFeePerGas) - 0.2 + ).toString(), + }, + medium: { + minWaitTimeEstimate: 1000, + maxWaitTimeEstimate: 2000, + suggestedMaxPriorityFeePerGas: ( + Number(maxPriorityFeePerGas) - 0.1 + ).toString(), + }, + high: { + suggestedMaxPriorityFeePerGas: ( + Number(maxPriorityFeePerGas) + 0.5 + ).toString(), + }, + }), + ); + + expect(timeBounds).toStrictEqual({ + lowerTimeBound: 1000, + upperTimeBound: 2000, + }); + }); + }); + + describe('and the given priority fee reaches the suggested high priority fee threshold', () => { + it('should return a lower and upper bound equal to the high min and max wait time', () => { + const timeBounds = calculateTimeEstimate( + maxPriorityFeePerGas, + maxFeePerGas, + buildGasFeeEstimates({ + estimatedBaseFee, + low: { + suggestedMaxPriorityFeePerGas: ( + Number(maxPriorityFeePerGas) - 0.2 + ).toString(), + }, + medium: { + suggestedMaxPriorityFeePerGas: ( + Number(maxPriorityFeePerGas) - 0.1 + ).toString(), + }, + high: { + minWaitTimeEstimate: 1000, + maxWaitTimeEstimate: 2000, + suggestedMaxPriorityFeePerGas: maxPriorityFeePerGas, + }, + }), + ); + + expect(timeBounds).toStrictEqual({ + lowerTimeBound: 1000, + upperTimeBound: 2000, + }); + }); + }); + + describe('and the given priority fee exceeds the suggested high priority fee threshold', () => { + it('should return a lower bound of 0 and an upper bound equal to the high max wait time', () => { + const timeBounds = calculateTimeEstimate( + maxPriorityFeePerGas, + maxFeePerGas, + buildGasFeeEstimates({ + estimatedBaseFee, + low: { + suggestedMaxPriorityFeePerGas: ( + Number(maxPriorityFeePerGas) - 0.3 + ).toString(), + }, + medium: { + suggestedMaxPriorityFeePerGas: ( + Number(maxPriorityFeePerGas) - 0.2 + ).toString(), + }, + high: { + maxWaitTimeEstimate: 2000, + suggestedMaxPriorityFeePerGas: ( + Number(maxPriorityFeePerGas) - 0.1 + ).toString(), + }, + }), + ); + + expect(timeBounds).toStrictEqual({ + lowerTimeBound: 0, + upperTimeBound: 2000, + }); + }); + }); }); - it('should handle NaN', () => { - expect(normalizeGWEIDecimalNumbers(NaN)).toBe('0'); + describe('if the given priority fee is greater than the given max fee minus the latest base fee (aka the effective priority fee)', () => { + let maxPriorityFeePerGas: string; + let maxFeePerGas: string; + let estimatedBaseFee: string; + let effectivePriorityFeePerGas: string; + + beforeEach(() => { + maxPriorityFeePerGas = '2'; + effectivePriorityFeePerGas = '1'; + estimatedBaseFee = '100'; + maxFeePerGas = ( + Number(estimatedBaseFee) + Number(effectivePriorityFeePerGas) + ).toString(); + }); + + describe('and the effective priority fee does not reach any of the suggested priority fee thresholds', () => { + it('should return no lower bound and an unknown upper bound', () => { + const timeBounds = calculateTimeEstimate( + maxPriorityFeePerGas, + maxFeePerGas, + buildGasFeeEstimates({ + estimatedBaseFee, + low: { + suggestedMaxPriorityFeePerGas: ( + Number(effectivePriorityFeePerGas) + 0.5 + ).toString(), + }, + }), + ); + + expect(timeBounds).toStrictEqual({ + lowerTimeBound: null, + upperTimeBound: 'unknown', + }); + }); + }); + + describe('and the effective priority fee reaches the suggested low priority fee threshold, but does reach the medium priority fee threshold', () => { + it('should return a lower and upper bound equal to the low min and max wait time', () => { + const timeBounds = calculateTimeEstimate( + maxPriorityFeePerGas, + maxFeePerGas, + buildGasFeeEstimates({ + estimatedBaseFee, + low: { + minWaitTimeEstimate: 1000, + maxWaitTimeEstimate: 2000, + suggestedMaxPriorityFeePerGas: effectivePriorityFeePerGas, + }, + medium: { + suggestedMaxPriorityFeePerGas: ( + Number(effectivePriorityFeePerGas) + 0.5 + ).toString(), + }, + }), + ); + + expect(timeBounds).toStrictEqual({ + lowerTimeBound: 1000, + upperTimeBound: 2000, + }); + }); + }); + + describe('and the effective priority fee exceeds the suggested low priority fee threshold, but does reach the medium priority fee threshold', () => { + it('should return a lower and upper bound equal to the low min and max wait time', () => { + const timeBounds = calculateTimeEstimate( + maxPriorityFeePerGas, + maxFeePerGas, + buildGasFeeEstimates({ + estimatedBaseFee, + low: { + minWaitTimeEstimate: 1000, + maxWaitTimeEstimate: 2000, + suggestedMaxPriorityFeePerGas: ( + Number(effectivePriorityFeePerGas) - 0.1 + ).toString(), + }, + medium: { + suggestedMaxPriorityFeePerGas: ( + Number(effectivePriorityFeePerGas) + 0.5 + ).toString(), + }, + }), + ); + + expect(timeBounds).toStrictEqual({ + lowerTimeBound: 1000, + upperTimeBound: 2000, + }); + }); + }); + + describe('and the effective priority fee reaches the suggested medium priority fee threshold, but does not cross the suggested high priority fee threshold', () => { + it('should return a lower and upper bound equal to the medium min and max wait time', () => { + const timeBounds = calculateTimeEstimate( + maxPriorityFeePerGas, + maxFeePerGas, + buildGasFeeEstimates({ + estimatedBaseFee, + low: { + suggestedMaxPriorityFeePerGas: ( + Number(effectivePriorityFeePerGas) - 0.1 + ).toString(), + }, + medium: { + minWaitTimeEstimate: 1000, + maxWaitTimeEstimate: 2000, + suggestedMaxPriorityFeePerGas: effectivePriorityFeePerGas, + }, + high: { + suggestedMaxPriorityFeePerGas: ( + Number(effectivePriorityFeePerGas) + 0.5 + ).toString(), + }, + }), + ); + + expect(timeBounds).toStrictEqual({ + lowerTimeBound: 1000, + upperTimeBound: 2000, + }); + }); + }); + + describe('and the effective priority fee exceeds the suggested medium priority fee threshold, but does not cross the suggested high priority fee threshold', () => { + it('should return a lower and upper bound equal to the medium min and max wait time', () => { + const timeBounds = calculateTimeEstimate( + maxPriorityFeePerGas, + maxFeePerGas, + buildGasFeeEstimates({ + estimatedBaseFee, + low: { + suggestedMaxPriorityFeePerGas: ( + Number(effectivePriorityFeePerGas) - 0.2 + ).toString(), + }, + medium: { + minWaitTimeEstimate: 1000, + maxWaitTimeEstimate: 2000, + suggestedMaxPriorityFeePerGas: ( + Number(effectivePriorityFeePerGas) - 0.1 + ).toString(), + }, + high: { + suggestedMaxPriorityFeePerGas: ( + Number(effectivePriorityFeePerGas) + 0.5 + ).toString(), + }, + }), + ); + + expect(timeBounds).toStrictEqual({ + lowerTimeBound: 1000, + upperTimeBound: 2000, + }); + }); + }); + + describe('and the effective priority fee reaches the suggested high priority fee threshold', () => { + it('should return a lower and upper bound equal to the high min and max wait time', () => { + const timeBounds = calculateTimeEstimate( + maxPriorityFeePerGas, + maxFeePerGas, + buildGasFeeEstimates({ + estimatedBaseFee, + low: { + suggestedMaxPriorityFeePerGas: ( + Number(effectivePriorityFeePerGas) - 0.2 + ).toString(), + }, + medium: { + suggestedMaxPriorityFeePerGas: ( + Number(effectivePriorityFeePerGas) - 0.1 + ).toString(), + }, + high: { + minWaitTimeEstimate: 1000, + maxWaitTimeEstimate: 2000, + suggestedMaxPriorityFeePerGas: effectivePriorityFeePerGas, + }, + }), + ); + + expect(timeBounds).toStrictEqual({ + lowerTimeBound: 1000, + upperTimeBound: 2000, + }); + }); + }); + + describe('and the effective priority fee exceeds the suggested high priority fee threshold', () => { + it('should return a lower bound of 0 and an upper bound equal to the high max wait time', () => { + const timeBounds = calculateTimeEstimate( + maxPriorityFeePerGas, + maxFeePerGas, + buildGasFeeEstimates({ + estimatedBaseFee, + low: { + suggestedMaxPriorityFeePerGas: ( + Number(effectivePriorityFeePerGas) - 0.3 + ).toString(), + }, + medium: { + suggestedMaxPriorityFeePerGas: ( + Number(effectivePriorityFeePerGas) - 0.2 + ).toString(), + }, + high: { + maxWaitTimeEstimate: 2000, + suggestedMaxPriorityFeePerGas: ( + Number(effectivePriorityFeePerGas) - 0.1 + ).toString(), + }, + }), + ); + + expect(timeBounds).toStrictEqual({ + lowerTimeBound: 0, + upperTimeBound: 2000, + }); + }); + }); }); }); }); From 75faa8882012ec808398a1dec785d78b37ac9302 Mon Sep 17 00:00:00 2001 From: Elliot Winkler Date: Tue, 29 Mar 2022 13:54:39 -0600 Subject: [PATCH 2/2] Add docs for buildGasFeeEstimates, simplify --- src/gas/gas-util.test.ts | 43 +++++++++++++++++----------------------- 1 file changed, 18 insertions(+), 25 deletions(-) diff --git a/src/gas/gas-util.test.ts b/src/gas/gas-util.test.ts index ce25be41602..2f98c167a6e 100644 --- a/src/gas/gas-util.test.ts +++ b/src/gas/gas-util.test.ts @@ -9,6 +9,10 @@ import { calculateTimeEstimate, } from './gas-util'; +type DeeplyPartial = T extends Record + ? { [K in keyof T]?: DeeplyPartial } + : T; + const mockEIP1559ApiResponses = [ { low: { @@ -242,29 +246,18 @@ describe('gas-util', () => { }); describe('calculateTimeEstimate', () => { - const buildGasFeeEstimates = ({ - estimatedBaseFee, - low = {}, - medium = {}, - high = {}, - }: { - estimatedBaseFee: string; - low?: { - minWaitTimeEstimate?: number; - maxWaitTimeEstimate?: number; - suggestedMaxPriorityFeePerGas?: string; - }; - medium?: { - minWaitTimeEstimate?: number; - maxWaitTimeEstimate?: number; - suggestedMaxPriorityFeePerGas?: string; - }; - high?: { - minWaitTimeEstimate?: number; - maxWaitTimeEstimate?: number; - suggestedMaxPriorityFeePerGas?: string; - }; - }): GasFeeEstimates => { + /** + * Allows building a GasFeeEstimates object in tests by specifying only the + * properties of the object that matter to those tests. + * + * @param overrides - The properties you want to override in the new + * GasFeeEstimates object. + * @returns The built GasFeeEstimates object. + */ + function buildGasFeeEstimates( + overrides: DeeplyPartial, + ): GasFeeEstimates { + const { low = {}, medium = {}, high = {}, estimatedBaseFee } = overrides; return { low: { minWaitTimeEstimate: 0, @@ -295,7 +288,7 @@ describe('gas-util', () => { priorityFeeTrend: null, networkCongestion: null, }; - }; + } describe('if the given priority fee is less than the given max fee minus the latest base fee', () => { let maxPriorityFeePerGas: string; @@ -330,7 +323,7 @@ describe('gas-util', () => { }); }); - describe('and the given priority fee reaches the suggested low priority fee threshold, but does reach the medium priority fee threshold', () => { + describe('and the given priority fee reaches the suggested low priority fee threshold, but does not reach the medium priority fee threshold', () => { it('should return a lower and upper bound equal to the low min and max wait time', () => { const timeBounds = calculateTimeEstimate( maxPriorityFeePerGas,