Skip to content

Commit

Permalink
chore(release): merge pull request #5270 from cowprotocol/release/202…
Browse files Browse the repository at this point in the history
…5-01-07

* fix: adjust cow amm banner position (#5205)

* feat: use new uni and coingecko token lists (#5225)

* feat: use new uni and coingecko token lists

* fix: linter errors

* fix(limit-orders): do not override user entered price (#5232)

* fix: allow any safe-like apps (#5235)

* fix(feature-flags): remove isBaseEnabled feature flag (#5234)

* feat(wallets): reapply "feat(wallets): add metaMask SDK connector (#5028)" (#5215) (#5223)

* Reapply "feat(wallets): add metaMask SDK connector (#5028)" (#5215)

This reverts commit 889b78e.

* chore: update MetaMask SDK to 0.31.4

---------

Co-authored-by: Leandro <[email protected]>

* chore: merge main to dev (#5238)

* fix: allow any safe-like apps

* chore: release main (#5237)

* feat: fix pagination for fills (#5228)

* feat: fix pagination for fills

* fix: remove unnecessary tag

---------

Co-authored-by: Alexandr Kazachenko <[email protected]>

* feat(token-lists): remove outdated token lists (#5233)

* feat: remove outdated token lists

* feat: add curve's list to base

* feat: add superchain list to base

* chore: fix failed e2e test (#5257)

* chore: address pr5244 comments (#5263)

* fix: use network instead of orderParams chainId

* refactor: update comment

* ci: deploy some apps preview only when PR has label (#5258)

* feat: executedSurplusFee removal (#5262)

* chore: bump cow-sdk to latest RC version

* feat: replace executedSurplusFee with executedSuplus

Also use totalFee where applicable

* feat: do same as previous, but on Explorer

* refactor: moved getFeeToken out and improved logic as suggested

* test: add unit tests

* chore: comment out seasonal feature flags (#5271)

* feat(swap): partial approve (#5256)

* feat(swap): add settings option for partial approve

* feat(swap): add sell amount to regular approve tx

* feat(swap): add sell amount to permit value

* chore: fix build

* fix: cache permit taking amount into account

* feat(swap): take partial approves into account for sc wallets

* fix: ignore account agnostic permit in hooks details

* fix: take permit amount into account when caching

* fix: skip partial permits in widgets besides swap

* chore: fix permit hook description

* chore: fix conditions

* fix: disable partial approve for Hooks store

* fix: support partial approve it classic eth flow

* fix: do not use infinite approvals in swap when partial approve mode

* chore: fix circular dependency

* chore: add a dot

* chore: fix tooltips

* chore: adjust approve tooltip

* fix: display hook details only in Hooks store confirm modal

* feat(partial-approvals): partial approve v2 (#5269)

* refactor: expose UndelinedLinkStyledButton component

* chore: removed unused React import

* refactor: export useOpenSettingsTab hook

* feat: expose needsApproval flag for all token types, not just permittable

* feat: add PartialApprovalBanner

* feat: update settings name Partial Approve to Minimal approve and tooltip

* fix: fix typo and padding on settings link

* fix: reworked minimal approvals title and tooltip

* fix: lint issues

* fix: cosmos build

* fix: fix grammar

* fix: do not show approval banner when selling native

* chore: move partial approval banner after TWAP warning

* feat: simplify text

* feat: remove isApprovalNeeded prop

* feat: remove banner from swap warnings

* feat: add banner to top of Swap widget

* chore: remove settings from cosmos

---------

Co-authored-by: Leandro <[email protected]>

---------

Co-authored-by: fairlight <[email protected]>
Co-authored-by: Anxo Rodriguez <[email protected]>
Co-authored-by: Alexandr Kazachenko <[email protected]>
Co-authored-by: Edouard Bougon <[email protected]>
  • Loading branch information
5 people authored Jan 9, 2025
2 parents 935aeda + 7a1ce48 commit 6d4cb49
Show file tree
Hide file tree
Showing 35 changed files with 977 additions and 203 deletions.
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,21 @@ In case of problems with the service worker cache you force a reset using
`emergency.js` is not cached by browser and loaded before all.
## Vercel preview build
Since this repo includes multiple apps, we do not want to build all of them on each PR because it causes long build queues in Vercel.
Some apps (see the list bellow) are not required to be built on each PR so we run them only a PR is labeled with a specific label.
This label is defined in the project settings on Vercel in `Settings`/`Git`/`Ignored Build Step` script.
For example, the label for the widget-configurator is `preview-widget-cfg`:
```
node tools/scripts/ignore-build-step.js --app=preview-widget-cfg
```
List of applications and their labels:
- widget-configurator: `preview-widget-cfg`
- cosmos: `preview-cosmos`
- sdk-tools: `preview-sdk-tools`
# 📚 Technical Documentation
1. [Oveall Architecture](docs/architecture-overview.md)
Expand Down
2 changes: 1 addition & 1 deletion apps/cowswap-frontend-e2e/src/e2e/swap.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ describe('Swap (custom)', () => {
})

it('should accept buyAmount url param', () => {
cy.visit(`/#/${CHAIN_ID}/swap/${SELL_TOKEN}/${BUY_TOKEN}?buyAmount=0.5`)
cy.visit(`/#/${CHAIN_ID}/swap/${SELL_TOKEN}/${BUY_TOKEN}?buyAmount=0.5&orderKind=buy`)
cy.get('#output-currency-input .token-amount-input').should('have.value', '0.5')
})

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { isTruthy } from '@cowprotocol/common-utils'
import { TokensByAddress } from '@cowprotocol/tokens'
import { LpTokenProvider } from '@cowprotocol/types'

import styled from 'styled-components/macro'

import { upToSmall, useMediaQuery } from 'legacy/hooks/useMediaQuery'

import { VampireAttackContext } from 'modules/yield/types'
Expand All @@ -17,6 +19,10 @@ import { CoWAmmBannerContext } from './types'

import { useSafeMemoObject } from '../../hooks/useSafeMemo'

const Wrapper = styled.div`
z-index: 100;
`

interface CoWAmmBannerContentProps {
id: string
title: string
Expand Down Expand Up @@ -139,7 +145,7 @@ export function CoWAmmBannerContent({
)

return (
<div data-banner-id={id}>
<Wrapper data-banner-id={id}>
{isTokenSelectorView ? (
<TokenSelectorContent isDarkMode={isDarkMode} context={context}>
{Content}
Expand All @@ -159,6 +165,6 @@ export function CoWAmmBannerContent({
{Content}
</GlobalContent>
)}
</div>
</Wrapper>
)
}
11 changes: 8 additions & 3 deletions apps/cowswap-frontend/src/legacy/state/orders/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,9 @@ export type OrderInfoApi = Pick<
| 'executedSellAmount'
| 'executedSellAmountBeforeFees'
| 'executedFeeAmount'
| 'executedSurplusFee'
| 'executedFee'
| 'executedFeeToken'
| 'totalFee'
| 'invalidated'
| 'ethflowData'
| 'onchainOrderData'
Expand Down Expand Up @@ -139,6 +141,7 @@ export interface AddPendingOrderParams {
order: SerializedOrder
isSafeWallet: boolean
}

export type ChangeOrderStatusParams = { id: UID; chainId: ChainId }
export type SetOrderCancellationHashParams = ChangeOrderStatusParams & { hash: string }

Expand Down Expand Up @@ -177,11 +180,13 @@ export interface BatchOrdersUpdateParams {
}

export type PresignedOrdersParams = BatchOrdersUpdateParams

export interface UpdatePresignGnosisSafeTxParams {
orderId: UID
chainId: ChainId
safeTransaction: SafeMultisigTransactionResponse
}

export type ExpireOrdersBatchParams = BatchOrdersUpdateParams
export type InvalidateOrdersBatchParams = BatchOrdersUpdateParams
export type CancelOrdersBatchParams = BatchOrdersUpdateParams
Expand All @@ -196,7 +201,7 @@ export const fulfillOrdersBatch = createAction<FulfillOrdersBatchParams>('order/
export const preSignOrders = createAction<PresignedOrdersParams>('order/presignOrders')

export const updatePresignGnosisSafeTx = createAction<UpdatePresignGnosisSafeTxParams>(
'order/updatePresignGnosisSafeTx'
'order/updatePresignGnosisSafeTx',
)

export const expireOrdersBatch = createAction<ExpireOrdersBatchParams>('order/expireOrdersBatch')
Expand All @@ -214,7 +219,7 @@ export const deleteOrders = createAction<DeleteOrdersParams>('order/deleteOrders
export const clearOrders = createAction<{ chainId: ChainId }>('order/clearOrders')

export const updateLastCheckedBlock = createAction<{ chainId: ChainId; lastCheckedBlock: number }>(
'order/updateLastCheckedBlock'
'order/updateLastCheckedBlock',
)

export const clearOrdersStorage = createAction('order/clearOrdersStorage')
Expand Down
17 changes: 9 additions & 8 deletions apps/cowswap-frontend/src/legacy/state/orders/reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ export function getDefaultNetworkState(chainId: ChainId): OrdersStateNetwork {
// makes sure there's always an object at state[chainId], state[chainId].pending | .fulfilled
function prefillState(
state: Writable<OrdersState>,
{ payload: { chainId } }: PayloadAction<PrefillStateRequired>
{ payload: { chainId } }: PayloadAction<PrefillStateRequired>,
): asserts state is Required<OrdersState> {
const stateAtChainId = state[chainId]

Expand Down Expand Up @@ -174,7 +174,7 @@ function addOrderToState(
id: string,
status: OrderTypeKeys,
order: SerializedOrder,
isSafeWallet: boolean
isSafeWallet: boolean,
): void {
// Attempt to fix `TypeError: Cannot add property <x>, object is not extensible`
// seen on https://user-images.githubusercontent.com/34510341/138450105-bb94a2d1-656e-4e15-ae99-df9fb33c8ca4.png
Expand All @@ -200,7 +200,7 @@ function cancelOrderInState(
state: Required<OrdersState>,
chainId: ChainId,
orderObject: OrderObject,
isSafeWallet: boolean
isSafeWallet: boolean,
) {
const id = orderObject.id

Expand Down Expand Up @@ -368,12 +368,13 @@ export default createReducer(initialState, (builder) =>

orderObject.order.apiAdditionalInfo = {
creationDate: order.creationDate,
availableBalance: order.availableBalance,
executedBuyAmount: order.executedBuyAmount,
executedSellAmount: order.executedSellAmount,
executedSellAmountBeforeFees: order.executedSellAmountBeforeFees,
executedFeeAmount: order.executedFeeAmount,
executedSurplusFee: order.executedSurplusFee,
executedFee: order.executedFee,
executedFeeToken: order.executedFeeToken,
totalFee: order.totalFee,
invalidated: order.invalidated,
ethflowData: order.ethflowData,
onchainOrderData: order.onchainOrderData,
Expand Down Expand Up @@ -458,7 +459,7 @@ export default createReducer(initialState, (builder) =>
const allOrdersMap = flatOrdersStateNetwork(state[chainId])

const children = Object.values(allOrdersMap).filter(
(item) => item?.order.composableCowInfo?.parentId === id
(item) => item?.order.composableCowInfo?.parentId === id,
)

children.forEach((child) => {
Expand Down Expand Up @@ -544,12 +545,12 @@ export default createReducer(initialState, (builder) =>
orderListByChain[status] = ordersCleaned
})
})
})
}),
)

function reClassifyOrder(
newOrder: SerializedOrder,
existingOrder: OrderObject | undefined
existingOrder: OrderObject | undefined,
): { status: OrderStatus; isCancelling: boolean | undefined } {
// Onchain cancellations are considered final
// Still, the order classification at apps/cowswap-frontend/src/legacy/state/orders/utils.ts can't tell
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { lazy, PropsWithChildren, Suspense, useMemo } from 'react'

import { ACTIVE_CUSTOM_THEME, CustomTheme } from '@cowprotocol/common-const'
import { useMediaQuery } from '@cowprotocol/common-hooks'
import { useFeatureFlags } from '@cowprotocol/common-hooks'
import { useFeatureFlags, useMediaQuery } from '@cowprotocol/common-hooks'
import { isInjectedWidget } from '@cowprotocol/common-utils'
import { Color, Footer, GlobalCoWDAOStyles, Media, MenuBar } from '@cowprotocol/ui'

Expand Down Expand Up @@ -55,7 +54,10 @@ export function App() {
useAnalyticsReporterCowSwap()
useInitializeUtm()

const { isYieldEnabled, isChristmasEnabled, isHalloweenEnabled } = useFeatureFlags()
const { isYieldEnabled, } = useFeatureFlags()
// TODO: load them from feature flags when we want to enable again
const isChristmasEnabled = false
const isHalloweenEnabled = false

const isInjectedWidgetMode = isInjectedWidget()
const menuItems = useMenuItems()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,37 +1,37 @@
import { useSetAtom } from 'jotai'
import { useLayoutEffect, useState } from 'react'
import { useAtomValue, useSetAtom } from 'jotai'
import { useEffect, useLayoutEffect, useState } from 'react'

import { usePrevious } from '@cowprotocol/common-hooks'

import { Writeable } from 'types'

import { useGetInitialPrice } from 'modules/limitOrders/hooks/useGetInitialPrice'
import { useUpdateActiveRate } from 'modules/limitOrders/hooks/useUpdateActiveRate'
import { LimitRateState, updateLimitRateAtom } from 'modules/limitOrders/state/limitRateAtom'

import { useLimitOrdersDerivedState } from '../../hooks/useLimitOrdersDerivedState'
import { useGetInitialPrice } from '../../hooks/useGetInitialPrice'
import { useLimitOrdersRawState } from '../../hooks/useLimitOrdersRawState'
import { useUpdateActiveRate } from '../../hooks/useUpdateActiveRate'
import { limitRateAtom, LimitRateState, updateLimitRateAtom } from '../../state/limitRateAtom'

// Fetch and update initial price for the selected token pair
export function InitialPriceUpdater() {
const { inputCurrency, outputCurrency } = useLimitOrdersDerivedState()
const { inputCurrencyId, outputCurrencyId } = useLimitOrdersRawState()
const { isTypedValue } = useAtomValue(limitRateAtom)
const updateLimitRateState = useSetAtom(updateLimitRateAtom)
const updateRate = useUpdateActiveRate()

const [isInitialPriceSet, setIsInitialPriceSet] = useState(false)
const [isInitialPriceSet, setIsInitialPriceSet] = useState(isTypedValue)
const { price, isLoading } = useGetInitialPrice()
const prevPrice = usePrevious(price)

useEffect(() => {
setIsInitialPriceSet(isTypedValue)
}, [isTypedValue])

useLayoutEffect(() => {
const update: Partial<Writeable<LimitRateState>> = {
initialRate: price,
// Don't change isLoading flag when price is already set
isLoading: isInitialPriceSet ? false : isLoading,
}

if (!isInitialPriceSet) {
update.isTypedValue = false
}

updateLimitRateState(update)
}, [isInitialPriceSet, price, isLoading, updateLimitRateState])

Expand All @@ -40,6 +40,7 @@ export function InitialPriceUpdater() {
if (!price || isInitialPriceSet || isLoading || prevPrice?.equalTo(price)) return

setIsInitialPriceSet(true)

updateRate({
activeRate: price,
isInitialPriceSet: true,
Expand All @@ -53,7 +54,7 @@ export function InitialPriceUpdater() {
// Reset initial price set flag when any token was changed
useLayoutEffect(() => {
setIsInitialPriceSet(false)
}, [inputCurrency, outputCurrency])
}, [inputCurrencyId, outputCurrencyId])

return null
}
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,19 @@ export const ordersMock: ParsedOrder[] = [
signingScheme: SigningScheme.EIP712,
class: OrderClass.MARKET,
kind: OrderKind.SELL,
apiAdditionalInfo: {
executedFeeAmount: '1',
executedFee: '1',
executedFeeToken: USDC[chainId].address,
totalFee: '1',
creationDate: '2022-11-11T13:15:13.551Z',
executedBuyAmount: '23000000000000',
executedSellAmount: '5000300000000000',
executedSellAmountBeforeFees: '5000300000000000',
invalidated: false,
class: OrderClass.LIMIT,
signingScheme: SigningScheme.EIP712,
},
},
{
id: '5',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,29 +1,30 @@
import { TokenAmount } from '@cowprotocol/ui'
import { CurrencyAmount } from '@uniswap/sdk-core'

import { getFeeToken } from 'modules/ordersTable/utils/getFeeToken'

import { ParsedOrder } from 'utils/orderUtils/parseOrder'

import * as styledEl from './styled'

export type Props = { order: ParsedOrder }

export function FeeField({ order }: Props): JSX.Element | null {
const { inputToken } = order
const { executedFeeAmount, executedSurplusFee } = order.executionData
const { totalFee } = order.executionData
const feeToken = getFeeToken(order)

if (!inputToken) return <styledEl.Value></styledEl.Value>
if (!feeToken) return <styledEl.Value></styledEl.Value>

// TODO: use the value from SDK
const totalFee = CurrencyAmount.fromRawAmount(inputToken, (executedSurplusFee ?? executedFeeAmount) || 0)
const quoteSymbol = inputToken.symbol
const totalFeeAmount = CurrencyAmount.fromRawAmount(feeToken, totalFee || 0)
const quoteSymbol = feeToken.symbol

return (
<styledEl.Value>
{!quoteSymbol || !totalFee ? (
<span>-</span>
) : (
<span>
<TokenAmount amount={totalFee} tokenSymbol={inputToken} />
<TokenAmount amount={totalFeeAmount} tokenSymbol={feeToken} />
</span>
)}
</styledEl.Value>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { getFeeToken } from './getFeeToken' // Adjust the import path as necessary

import { ordersMock } from '../pure/OrdersTableContainer/orders.mock'

const BASE_ORDER = ordersMock[3]

describe('getFeeToken', () => {
it("should return inputToken when that's the fee token", () => {
const input = BASE_ORDER
const expectedOutput = BASE_ORDER.inputToken

const result = getFeeToken(input)

expect(result).toEqual(expectedOutput)
})

it("should return outputToken when that's the fee token", () => {
const input = {
...BASE_ORDER,
executionData: { ...BASE_ORDER.executionData, executedFeeToken: BASE_ORDER.outputToken.address },
}
const expectedOutput = BASE_ORDER.outputToken

const result = getFeeToken(input)

expect(result).toEqual(expectedOutput)
})

it('should return inputToken when there is no fee token', () => {
const input = { ...BASE_ORDER, executionData: { ...BASE_ORDER.executionData, executedFeeToken: null } }
const expectedOutput = BASE_ORDER.inputToken

const result = getFeeToken(input)

expect(result).toEqual(expectedOutput)
})
})
14 changes: 14 additions & 0 deletions apps/cowswap-frontend/src/modules/ordersTable/utils/getFeeToken.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { ParsedOrder } from 'utils/orderUtils/parseOrder'

export function getFeeToken(order: ParsedOrder) {
const { inputToken, outputToken } = order
const { executedFeeToken } = order.executionData

const feeTokenAddress = executedFeeToken?.toLowerCase()

if (!feeTokenAddress) {
return inputToken
}

return [inputToken, outputToken].find((token) => token?.address.toLowerCase() === feeTokenAddress)
}
Loading

0 comments on commit 6d4cb49

Please sign in to comment.