Skip to content
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ env:
REACT_APP_PINATA_API_KEY: ${{ secrets.REACT_APP_PINATA_API_KEY }}
REACT_APP_PINATA_SECRET_API_KEY: ${{ secrets.REACT_APP_PINATA_SECRET_API_KEY }}
REACT_APP_GOOGLE_ANALYTICS_ID: ${{ secrets.REACT_APP_GOOGLE_ANALYTICS_ID }}
REACT_APP_BLOCKNATIVE_API_KEY: ${{ secrets.REACT_APP_BLOCKNATIVE_API_KEY }}
REACT_APP_BFF_BASE_URL: ${{ secrets.BFF_BASE_URL }}
REACT_APP_BALANCES_WATCHER_BASE_URL: ${{ secrets.BALANCES_WATCHER_BASE_URL }}
REACT_APP_CMS_BASE_URL: ${{ secrets.CMS_BASE_URL }}
Expand Down
1 change: 0 additions & 1 deletion .github/workflows/ipfs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ env:
REACT_APP_PINATA_API_KEY: ${{ secrets.REACT_APP_PINATA_API_KEY }}
REACT_APP_PINATA_SECRET_API_KEY: ${{ secrets.REACT_APP_PINATA_SECRET_API_KEY }}
REACT_APP_GOOGLE_ANALYTICS_ID: ${{ secrets.REACT_APP_GOOGLE_ANALYTICS_ID }}
REACT_APP_BLOCKNATIVE_API_KEY: ${{ secrets.REACT_APP_BLOCKNATIVE_API_KEY }}
# Duplicated keys as these are required by `ipfs-deploy`
IPFS_DEPLOY_PINATA__API_KEY: ${{ secrets.REACT_APP_PINATA_API_KEY }}
IPFS_DEPLOY_PINATA__SECRET_API_KEY: ${{ secrets.REACT_APP_PINATA_SECRET_API_KEY }}
Expand Down
1 change: 1 addition & 0 deletions apps/cowswap-frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@
"@tanstack/react-virtual": "3.13.12",
"@uniswap/token-lists": "1.0.0-beta.33",
"@use-gesture/react": "10.3.1",
"@wagmi/core": "3.4.8",
"bignumber.js": "9.1.2",
"buffer": "6.0.3",
"color2k": "2.0.2",
Expand Down
110 changes: 41 additions & 69 deletions apps/cowswap-frontend/src/api/gasPrices/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { GAS_API_KEYS, GAS_FEE_ENDPOINTS } from '@cowprotocol/common-const'
import { SupportedChainId as ChainId } from '@cowprotocol/cow-sdk'
import { GAS_FEE_ENDPOINTS } from '@cowprotocol/common-const'
import { isEvmChain, SupportedChainId as ChainId } from '@cowprotocol/cow-sdk'
import { reownWagmiConfig } from '@cowprotocol/wallet'

import { getGasPrice } from '@wagmi/core'

import { fetchWithRateLimit } from 'common/utils/fetch'

Expand All @@ -20,45 +23,20 @@ export type GasFeeEndpointResponse = {
slow: string | null
}

export interface EstimatedPrice {
confidence: number
price: number
maxFeePerGas: number
maxPriorityFeePerGas: number
}

type GasPrices = Omit<GasFeeEndpointResponse, 'lastUpdate'>

// Here the key is what we use in gas state and the value is confidence level
// coming from the Blockscout api, so we map state values with confidence lvls
const priceMap: GasPrices = {
fast: '99',
average: '90',
slow: '70',
}
// The Blockscout gas price oracle returns prices (floats in gwei) for these confidence levels
const PRICE_KEYS: Array<keyof GasPrices> = ['fast', 'average', 'slow']

class GasFeeApi {
getUrl(chainId: ChainId): string {
return GAS_FEE_ENDPOINTS[chainId]
}

supportedChain(chainId: ChainId): boolean {
return !!GAS_FEE_ENDPOINTS[chainId]
}

getHeaders(chainId: ChainId): { headers?: Headers } {
// TODO: Replace any with proper type definitions
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const headers: { [key: string]: any } = {}
const apiKey = GAS_API_KEYS[chainId]

if (apiKey) {
headers.headers = new Headers({
Authorization: apiKey,
})
}

return headers
// Gas prices come either from the Blockscout oracle or, as a fallback, from the
// eth_gasPrice RPC method - both of which only apply to EVM chains.
return isEvmChain(chainId)
}

toWei(input: number | null): string | null {
Expand All @@ -69,61 +47,55 @@ class GasFeeApi {
return Math.floor(input * ONE_GWEI).toString()
}

getBlocknativePrice(data: EstimatedPrice[], lvl: string | null): number | null {
if (!data || !lvl) {
return null
}

const price = data.find(({ confidence }: EstimatedPrice) => lvl === String(confidence))?.price

return price || null
}

// TODO: Replace any with proper type definitions
// eslint-disable-next-line @typescript-eslint/no-explicit-any
parseData(json: any, chainId: ChainId): GasFeeEndpointResponse {
// Parse data from the Blockscout gas price oracle, e.g. { "slow": 0.16, "average": 0.44, "fast": 2.06 }
parseData(json: Record<keyof GasPrices, number>): GasFeeEndpointResponse {
const output: GasFeeEndpointResponse = {
lastUpdate: new Date().toISOString(),
fast: null,
average: null,
slow: null,
}

if (this.getUrl(chainId).match(/blocknative/)) {
// Parse data from Blocknative
const prices = json?.blockPrices[0]?.estimatedPrices

if (prices) {
for (const [key, value] of Object.entries(priceMap)) {
const price = this.getBlocknativePrice(prices, value)
output[key as keyof GasPrices] = this.toWei(price)
}
}
} else {
// Parse data from Blockscout
for (const key of Object.keys(priceMap)) {
output[key as keyof GasPrices] = this.toWei(json[key])
}
for (const key of PRICE_KEYS) {
output[key] = this.toWei(json[key])
}

return output
}

// TODO: Add proper return type annotation
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
async fetchData(chainId: ChainId) {
const url = this.getUrl(chainId)
const headers = this.getHeaders(chainId)
const response = await fetchRateLimited(url, headers)
async fetchData(url: string): Promise<Record<keyof GasPrices, number>> {
const response = await fetchRateLimited(url)

return response.json()
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}

// Fallback used when there is no gas price oracle endpoint for the network,
// or when the request to it failed. Returns the same value for all confidence levels.
async getGasPriceFromRpc(chainId: ChainId): Promise<GasFeeEndpointResponse> {
const gasPrice = (await getGasPrice(reownWagmiConfig, { chainId })).toString()

return {
lastUpdate: new Date().toISOString(),
fast: gasPrice,
average: gasPrice,
slow: gasPrice,
}
}

async getGasPrices(chainId: ChainId = ChainId.MAINNET): Promise<GasFeeEndpointResponse> {
const data = await this.fetchData(chainId)
const parsed = this.parseData(data, chainId)
const url = this.getUrl(chainId)

if (url) {
try {
const data = await this.fetchData(url)

return this.parseData(data)
} catch (error) {
console.error('[gasFeeApi] Failed to fetch gas prices from the oracle, falling back to RPC', error)
}
}

return parsed
return this.getGasPriceFromRpc(chainId)
}
}

Expand Down
80 changes: 0 additions & 80 deletions apps/cowswap-frontend/src/common/hooks/useNotificationState.ts

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ import { Trans } from '@lingui/react/macro'
import { ArrowLeft, ArrowRight } from 'react-feather'
import styled from 'styled-components/macro'

import NotificationBanner from 'legacy/components/NotificationBanner'

import { RequestCancellationModalProps } from './types'

import { CancellationType } from '../../hooks/useCancelOrder/state'
Expand Down Expand Up @@ -42,10 +40,15 @@ const TypeButton = styled.button<{ isOnChain$: boolean }>`
}
`

const StyledNotificationBanner = styled(NotificationBanner)`
const StyledNotificationBanner = styled.div`
margin-top: 15px;
margin-bottom: 0;
box-sizing: border-box;
padding: 8px;
background-color: var(${UI.COLOR_INFO_BG});
color: var(${UI.COLOR_INFO_TEXT});
font-size: 16px;
text-align: center;
border-radius: 8px;
`

const CancellationSummary = styled.span`
Expand Down Expand Up @@ -134,11 +137,9 @@ export function ModalTopContent(props: ModalTopContentProps): ReactNode {
successful.
</Trans>
{isOnChainType && (
<StyledNotificationBanner isVisible={true} canClose={false} level="INFO">
<div>
<Trans>Tx cost:</Trans>{' '}
{txCostAmount ? <TokenAmount amount={txCostAmount} tokenSymbol={nativeCurrency} /> : t`Unknown`}
</div>
<StyledNotificationBanner>
<Trans>Tx cost:</Trans>{' '}
{txCostAmount ? <TokenAmount amount={txCostAmount} tokenSymbol={nativeCurrency} /> : t`Unknown`}
</StyledNotificationBanner>
Comment thread
shoom3301 marked this conversation as resolved.
)}
</p>
Expand Down
61 changes: 0 additions & 61 deletions apps/cowswap-frontend/src/common/pure/CancellationModal/styled.tsx

This file was deleted.

Loading
Loading