diff --git a/packages/extension-base/src/services/chain-service/handler/EvmApi.ts b/packages/extension-base/src/services/chain-service/handler/EvmApi.ts index b5d21b2f73..c46bca0933 100644 --- a/packages/extension-base/src/services/chain-service/handler/EvmApi.ts +++ b/packages/extension-base/src/services/chain-service/handler/EvmApi.ts @@ -16,6 +16,7 @@ export class EvmApi implements _EvmApi { api: Web3; apiUrl: string; provider: HttpProvider | WebsocketProvider; + isTestnet?: boolean; apiError?: string; apiRetry = 0; public readonly isApiConnectedSubject = new BehaviorSubject(false); @@ -77,11 +78,12 @@ export class EvmApi implements _EvmApi { } } - constructor (chainSlug: string, apiUrl: string, { providerName }: _ApiOptions = {}) { + constructor (chainSlug: string, apiUrl: string, { isTestnet, providerName }: _ApiOptions = {}) { this.chainSlug = chainSlug; this.apiUrl = apiUrl; this.providerName = providerName || 'unknown'; this.provider = this.createProvider(apiUrl); + this.isTestnet = isTestnet; this.api = new Web3(this.provider); this.isReadyHandler = createPromiseHandler<_EvmApi>(); diff --git a/packages/extension-base/src/services/chain-service/handler/EvmChainHandler.ts b/packages/extension-base/src/services/chain-service/handler/EvmChainHandler.ts index f271be807f..9fd0ab43d0 100644 --- a/packages/extension-base/src/services/chain-service/handler/EvmChainHandler.ts +++ b/packages/extension-base/src/services/chain-service/handler/EvmChainHandler.ts @@ -40,7 +40,7 @@ export class EvmChainHandler extends AbstractChainHandler { this.evmApiMap[chainSlug] = evmApi; } - public async initApi (chainSlug: string, apiUrl: string, { onUpdateStatus, providerName }: Omit<_ApiOptions, 'metadata'> = {}) { + public async initApi (chainSlug: string, apiUrl: string, { isTestnet, onUpdateStatus, providerName }: Omit<_ApiOptions, 'metadata'> = {}) { const existed = this.getEvmApiByChain(chainSlug); if (existed) { @@ -53,7 +53,7 @@ export class EvmChainHandler extends AbstractChainHandler { return existed; } - const apiObject = new EvmApi(chainSlug, apiUrl, { providerName }); + const apiObject = new EvmApi(chainSlug, apiUrl, { isTestnet, providerName }); apiObject.connectionStatusSubject.subscribe(this.handleConnection.bind(this, chainSlug)); apiObject.connectionStatusSubject.subscribe(onUpdateStatus); diff --git a/packages/extension-base/src/services/chain-service/handler/types.ts b/packages/extension-base/src/services/chain-service/handler/types.ts index 8f95d2b622..b7749b9503 100644 --- a/packages/extension-base/src/services/chain-service/handler/types.ts +++ b/packages/extension-base/src/services/chain-service/handler/types.ts @@ -26,6 +26,7 @@ export interface _SubstrateChainSpec { export interface _ApiOptions { providerName?: string, + isTestnet?: boolean, metadata?: MetadataItem, onUpdateStatus?: (status: _ChainConnectionStatus) => void, externalApiPromise?: ApiPromise diff --git a/packages/extension-base/src/services/chain-service/index.ts b/packages/extension-base/src/services/chain-service/index.ts index cee8756817..84c4befe80 100644 --- a/packages/extension-base/src/services/chain-service/index.ts +++ b/packages/extension-base/src/services/chain-service/index.ts @@ -969,7 +969,8 @@ export class ChainService { } if (chainInfo.evmInfo !== null && chainInfo.evmInfo !== undefined) { - const chainApi = await this.evmChainHandler.initApi(chainInfo.slug, endpoint, { providerName, onUpdateStatus }); + const isTestnet = chainInfo.isTestnet; + const chainApi = await this.evmChainHandler.initApi(chainInfo.slug, endpoint, { isTestnet, providerName, onUpdateStatus }); this.evmChainHandler.setEvmApi(chainInfo.slug, chainApi); } diff --git a/packages/extension-base/src/services/chain-service/types.ts b/packages/extension-base/src/services/chain-service/types.ts index ab9e6e8ac8..347a4b5ef7 100644 --- a/packages/extension-base/src/services/chain-service/types.ts +++ b/packages/extension-base/src/services/chain-service/types.ts @@ -50,6 +50,7 @@ export interface _ChainBaseApi { chainSlug: string; apiUrl: string; providerName?: string; + isTestnet?: boolean; apiError?: string; apiRetry?: number; diff --git a/packages/extension-base/src/services/fee-service/utils/index.ts b/packages/extension-base/src/services/fee-service/utils/index.ts index 103574a0a6..fbf1a92178 100644 --- a/packages/extension-base/src/services/fee-service/utils/index.ts +++ b/packages/extension-base/src/services/fee-service/utils/index.ts @@ -10,6 +10,7 @@ import BigN from 'bignumber.js'; const INFURA_API_KEY = process.env.INFURA_API_KEY || ''; const INFURA_API_KEY_SECRET = process.env.INFURA_API_KEY_SECRET || ''; const INFURA_AUTH = 'Basic ' + Buffer.from(INFURA_API_KEY + ':' + INFURA_API_KEY_SECRET).toString('base64'); +const EIP1559_MIN_PRIORITY_FEE = '1'; export const parseInfuraFee = (info: InfuraFeeInfo, threshold: InfuraThresholdInfo): EvmFeeInfo => { const base = new BigN(info.estimatedBaseFee).multipliedBy(BN_WEI); @@ -167,15 +168,19 @@ export const calculateGasFeeParams = async (web3: _EvmApi, networkKey: string, u const averagePriorityFee = history.reward.reduce((previous, rewards) => previous.plus(rewards[1]), BN_ZERO).dividedBy(numBlock).decimalPlaces(0); const fastPriorityFee = history.reward.reduce((previous, rewards) => previous.plus(rewards[2]), BN_ZERO).dividedBy(numBlock).decimalPlaces(0); + const slowFee = enforceMinOneTip(getEIP1559GasFee(baseGasFee, slowPriorityFee, 30000), web3.isTestnet); + const averageFee = enforceMinOneTip(getEIP1559GasFee(baseGasFee, averagePriorityFee, 45000), web3.isTestnet); + const fastFee = enforceMinOneTip(getEIP1559GasFee(baseGasFee, fastPriorityFee, 60000), web3.isTestnet); + return { type: 'evm', gasPrice: undefined, baseGasFee: baseGasFee.toString(), busyNetwork, options: { - slow: getEIP1559GasFee(baseGasFee, slowPriorityFee, 30000), - average: getEIP1559GasFee(baseGasFee, averagePriorityFee, 45000), - fast: getEIP1559GasFee(baseGasFee, fastPriorityFee, 60000), + slow: slowFee, + average: averageFee, + fast: fastFee, default: busyNetwork ? 'average' : 'slow' } }; @@ -192,3 +197,13 @@ export const calculateGasFeeParams = async (web3: _EvmApi, networkKey: string, u }; } }; + +const enforceMinOneTip = (feeOptionDetail: EvmEIP1995FeeOptionDetail, isTestnet?: boolean): EvmEIP1995FeeOptionDetail => { + if (isTestnet && feeOptionDetail.maxPriorityFeePerGas === '0') { + feeOptionDetail.maxPriorityFeePerGas = EIP1559_MIN_PRIORITY_FEE; + + return feeOptionDetail; + } + + return feeOptionDetail; +};