Skip to content
Open
Show file tree
Hide file tree
Changes from all 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 @@ -83,6 +83,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 { wagmiAdapter } 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(wagmiAdapter.wagmiConfig, { 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