From 8c06e217c1916a77190c0fe551e371d6061de030 Mon Sep 17 00:00:00 2001 From: Brad Decker Date: Thu, 1 Jul 2021 15:37:37 -0500 Subject: [PATCH 1/2] update types to be more identifiable --- src/gas/GasFeeController.ts | 126 ++++++++++++++++++++---------------- 1 file changed, 71 insertions(+), 55 deletions(-) diff --git a/src/gas/GasFeeController.ts b/src/gas/GasFeeController.ts index 47384441273..9085a2f7a72 100644 --- a/src/gas/GasFeeController.ts +++ b/src/gas/GasFeeController.ts @@ -18,6 +18,11 @@ import { export type unknownString = 'unknown'; +export type FeeMarketEstimateType = 'fee-market'; +export type LegacyEstimateType = 'legacy'; +export type EthGasPriceEstimateType = 'eth_gasPrice'; +export type NoEstimateType = 'none'; + /** * Indicates which type of gasEstimate the controller is currently returning. * This is useful as a way of asserting that the shape of gasEstimates matches @@ -25,13 +30,17 @@ export type unknownString = 'unknown'; * has been fetched. */ export const GAS_ESTIMATE_TYPES = { - FEE_MARKET: 'fee-market' as const, - LEGACY: 'legacy' as const, - ETH_GASPRICE: 'eth_gasPrice' as const, - NONE: 'none' as const, + FEE_MARKET: 'fee-market' as FeeMarketEstimateType, + LEGACY: 'legacy' as LegacyEstimateType, + ETH_GASPRICE: 'eth_gasPrice' as EthGasPriceEstimateType, + NONE: 'none' as NoEstimateType, }; -export type GasEstimateType = typeof GAS_ESTIMATE_TYPES[keyof typeof GAS_ESTIMATE_TYPES]; +export type GasEstimateType = + | FeeMarketEstimateType + | EthGasPriceEstimateType + | LegacyEstimateType + | NoEstimateType; export interface EstimatedGasFeeTimeBounds { lowerTimeBound: number | null; @@ -87,16 +96,6 @@ export interface Eip1559GasFee { suggestedMaxFeePerGas: string; // a GWEI decimal number } -function isEIP1559GasFee(object: any): object is Eip1559GasFee { - return ( - 'minWaitTimeEstimate' in object && - 'maxWaitTimeEstimate' in object && - 'suggestedMaxPriorityFeePerGas' in object && - 'suggestedMaxFeePerGas' in object && - Object.keys(object).length === 4 - ); -} - /** * @type GasFeeEstimates * @@ -115,24 +114,36 @@ export interface GasFeeEstimates { estimatedBaseFee: string; } -function isEIP1559Estimate(object: any): object is GasFeeEstimates { - return ( - 'low' in object && - isEIP1559GasFee(object.low) && - 'medium' in object && - isEIP1559GasFee(object.medium) && - 'high' in object && - isEIP1559GasFee(object.high) && - 'estimatedBaseFee' in object - ); -} - const metadata = { gasFeeEstimates: { persist: true, anonymous: false }, estimatedGasFeeTimeBounds: { persist: true, anonymous: false }, gasEstimateType: { persist: true, anonymous: false }, }; +export type GasFeeStateEthGasPrice = { + gasFeeEstimates: EthGasPriceEstimate; + estimatedGasFeeTimeBounds: Record; + gasEstimateType: EthGasPriceEstimateType; +}; + +export type GasFeeStateFeeMarket = { + gasFeeEstimates: GasFeeEstimates; + estimatedGasFeeTimeBounds: EstimatedGasFeeTimeBounds | Record; + gasEstimateType: FeeMarketEstimateType; +}; + +export type GasFeeStateLegacy = { + gasFeeEstimates: LegacyGasPriceEstimate; + estimatedGasFeeTimeBounds: Record; + gasEstimateType: LegacyEstimateType; +}; + +export type GasFeeStateNoEstimates = { + gasFeeEstimates: Record; + estimatedGasFeeTimeBounds: Record; + gasEstimateType: NoEstimateType; +}; + /** * @type GasFeeState * @@ -141,15 +152,11 @@ const metadata = { * @property gasFeeEstimates - Gas fee estimate data based on new EIP-1559 properties * @property estimatedGasFeeTimeBounds - Estimates representing the minimum and maximum */ -export type GasFeeState = { - gasFeeEstimates: - | GasFeeEstimates - | EthGasPriceEstimate - | LegacyGasPriceEstimate - | Record; - estimatedGasFeeTimeBounds: EstimatedGasFeeTimeBounds | Record; - gasEstimateType: GasEstimateType; -}; +export type GasFeeState = + | GasFeeStateEthGasPrice + | GasFeeStateFeeMarket + | GasFeeStateLegacy + | GasFeeStateNoEstimates; const name = 'GasFeeController'; @@ -163,7 +170,7 @@ export type GetGasFeeState = { handler: () => GasFeeState; }; -const defaultState = { +const defaultState: GasFeeState = { gasFeeEstimates: {}, estimatedGasFeeTimeBounds: {}, gasEstimateType: GAS_ESTIMATE_TYPES.NONE, @@ -218,7 +225,7 @@ export class GasFeeController extends BaseController { never, never >; - state?: Partial; + state?: GasFeeState; fetchGasEstimates?: typeof defaultFetchGasEstimates; fetchEthGasPriceEstimate?: typeof defaultFetchEthGasPriceEstimate; fetchLegacyGasPriceEstimates?: typeof defaultFetchLegacyGasPriceEstimates; @@ -275,10 +282,7 @@ export class GasFeeController extends BaseController { * @returns GasFeeEstimates */ async _fetchGasFeeEstimateData(): Promise { - let estimates: GasFeeState['gasFeeEstimates']; - let estimatedGasFeeTimeBounds = {}; let isEIP1559Compatible; - let gasEstimateType: GasEstimateType = GAS_ESTIMATE_TYPES.NONE; const isMainnet = this.getIsMainnet(); try { isEIP1559Compatible = await this.getEIP1559Compatibility(); @@ -287,28 +291,46 @@ export class GasFeeController extends BaseController { isEIP1559Compatible = false; } + let newState: GasFeeState = { + gasFeeEstimates: {}, + estimatedGasFeeTimeBounds: {}, + gasEstimateType: GAS_ESTIMATE_TYPES.NONE, + }; + try { if (isEIP1559Compatible) { - estimates = await this.fetchGasEstimates(); + const estimates = await this.fetchGasEstimates(); const { suggestedMaxPriorityFeePerGas, suggestedMaxFeePerGas, } = estimates.medium; - estimatedGasFeeTimeBounds = this.getTimeEstimate( + const estimatedGasFeeTimeBounds = this.getTimeEstimate( suggestedMaxPriorityFeePerGas, suggestedMaxFeePerGas, ); - gasEstimateType = GAS_ESTIMATE_TYPES.FEE_MARKET; + newState = { + gasFeeEstimates: estimates, + estimatedGasFeeTimeBounds, + gasEstimateType: GAS_ESTIMATE_TYPES.FEE_MARKET, + }; } else if (isMainnet) { - estimates = await this.fetchLegacyGasPriceEstimates(); - gasEstimateType = GAS_ESTIMATE_TYPES.LEGACY; + const estimates = await this.fetchLegacyGasPriceEstimates(); + newState = { + gasFeeEstimates: estimates, + estimatedGasFeeTimeBounds: {}, + gasEstimateType: GAS_ESTIMATE_TYPES.LEGACY, + }; } else { throw new Error('Main gas fee/price estimation failed. Use fallback'); } } catch { try { - estimates = await this.fetchEthGasPriceEstimate(this.ethQuery); - gasEstimateType = GAS_ESTIMATE_TYPES.ETH_GASPRICE; + const estimates = await this.fetchEthGasPriceEstimate(this.ethQuery); + newState = { + gasFeeEstimates: estimates, + estimatedGasFeeTimeBounds: {}, + gasEstimateType: GAS_ESTIMATE_TYPES.ETH_GASPRICE, + }; } catch (error) { throw new Error( `Gas fee/price estimation failed. Message: ${error.message}`, @@ -316,12 +338,6 @@ export class GasFeeController extends BaseController { } } - const newState: GasFeeState = { - gasFeeEstimates: estimates, - estimatedGasFeeTimeBounds, - gasEstimateType, - }; - this.update(() => { return newState; }); @@ -396,7 +412,7 @@ export class GasFeeController extends BaseController { ): EstimatedGasFeeTimeBounds | Record { if ( !this.state.gasFeeEstimates || - !isEIP1559Estimate(this.state.gasFeeEstimates) + this.state.gasEstimateType !== GAS_ESTIMATE_TYPES.FEE_MARKET ) { return {}; } From de81a41aaf4ca506fc6c7a80434d437846899b66 Mon Sep 17 00:00:00 2001 From: Brad Decker Date: Fri, 2 Jul 2021 09:56:26 -0500 Subject: [PATCH 2/2] comments --- src/gas/GasFeeController.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/gas/GasFeeController.ts b/src/gas/GasFeeController.ts index 9085a2f7a72..f6d226ab7b5 100644 --- a/src/gas/GasFeeController.ts +++ b/src/gas/GasFeeController.ts @@ -18,9 +18,20 @@ import { export type unknownString = 'unknown'; +// Fee Market describes the way gas is set after the london hardfork, and was +// defined by EIP-1559. export type FeeMarketEstimateType = 'fee-market'; +// Legacy describes gasPrice estimates from before london hardfork, when the +// user is connected to mainnet and are presented with fast/average/slow +// estimate levels to choose from. export type LegacyEstimateType = 'legacy'; +// EthGasPrice describes a gasPrice estimate received from eth_gasPrice. Post +// london this value should only be used for legacy type transactions when on +// networks that support EIP-1559. This type of estimate is the most accurate +// to display on custom networks that don't support EIP-1559. export type EthGasPriceEstimateType = 'eth_gasPrice'; +// NoEstimate describes the state of the controller before receiving its first +// estimate. export type NoEstimateType = 'none'; /**