Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 18 commits into from
Jan 8, 2025
Merged
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
15 changes: 12 additions & 3 deletions apps/cowswap-frontend/src/common/pure/OrderProgressBarV2/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,16 @@ import { ExplorerDataType, getExplorerLink, getRandomInt, isSellOrder, shortenAd
import { OrderKind, SupportedChainId } from '@cowprotocol/cow-sdk'
import { TokenLogo } from '@cowprotocol/tokens'
import { Command } from '@cowprotocol/types'
import { Confetti, ExternalLink, InfoTooltip, ProductLogo, ProductVariant, TokenAmount, UI } from '@cowprotocol/ui'
import {
Confetti,
ExternalLink,
InfoTooltip,
ProductLogo,
ProductVariant,
TokenAmount,
UI,
UnderlinedLinkStyledButton,
} from '@cowprotocol/ui'
import { Currency, CurrencyAmount } from '@uniswap/sdk-core'

import { AnimatePresence, motion } from 'framer-motion'
Expand Down Expand Up @@ -1123,14 +1132,14 @@ function ExpiredStep(props: OrderProgressBarV2Props) {
<h3>The good news</h3>
<p>
Unlike on other exchanges, you won't be charged for this! Feel free to{' '}
<styledEl.Button
<UnderlinedLinkStyledButton
onClick={() => {
props.navigateToNewOrder?.()
trackNewOrderClick()
}}
>
place a new order
</styledEl.Button>{' '}
</UnderlinedLinkStyledButton>{' '}
without worry.
</p>
</styledEl.InfoCard>
Expand Down
12 changes: 2 additions & 10 deletions apps/cowswap-frontend/src/common/pure/OrderProgressBarV2/styled.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import IMAGE_STAR_SHINE from '@cowprotocol/assets/cow-swap/star-shine.svg'
import { SingleLetterLogoWrapper } from '@cowprotocol/tokens'
import { ButtonPrimary, Font, LinkStyledButton, Media, UI } from '@cowprotocol/ui'
import { ButtonPrimary, Font, Media, UI } from '@cowprotocol/ui'

import styled, { css, keyframes } from 'styled-components/macro'

Expand Down Expand Up @@ -66,6 +66,7 @@ export const StepsContainer = styled.div<{ $height: number; $minHeight?: string;
padding: 0;

// implement a gradient to hide the bottom of the steps container using white to opacity white using pseudo element

&::after {
content: ${({ bottomGradient }) => (bottomGradient ? '""' : 'none')};
position: absolute;
Expand Down Expand Up @@ -143,15 +144,6 @@ export const CancelButton = styled(CancelButtonOriginal)`
}
`

export const Button = styled(LinkStyledButton)`
font-size: 14px;
text-decoration: underline;

&:hover {
text-decoration: none;
}
`

export const ProgressImageWrapper = styled.div<{ bgColor?: string; padding?: string; height?: string; gap?: string }>`
width: 100%;
height: ${({ height }) => height || '246px'};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import ICON_TOKENS from '@cowprotocol/assets/svg/tokens.svg'
import { Command } from '@cowprotocol/types'
import { BannerOrientation, ClosableBanner, InlineBanner, UnderlinedLinkStyledButton } from '@cowprotocol/ui'

import styled from 'styled-components/macro'

const BANNER_STORAGE_KEY = 'partialPermitBannerKey:v0'

type PartialApprovalBannerProps = {
openSettings: Command
}

export function PartialApprovalBanner({ openSettings }: PartialApprovalBannerProps) {
return ClosableBanner(BANNER_STORAGE_KEY, (onClose) => (
<InlineBanner
bannerType="success"
orientation={BannerOrientation.Horizontal}
customIcon={ICON_TOKENS}
iconSize={32}
onClose={onClose}
>
<p>
<b>NEW: </b>You can now choose to do minimal token approvals in the <Link onClick={openSettings}>settings</Link>.
</p>
</InlineBanner>
))
}

const Link = styled(UnderlinedLinkStyledButton)`
padding: 0;
`
Original file line number Diff line number Diff line change
Expand Up @@ -125,12 +125,19 @@ export function SettingsTab({
<RowBetween>
<RowFixed>
<ThemedText.Black fontWeight={400} fontSize={14}>
<Trans>Partial Approve</Trans>
<Trans>Minimal Approvals</Trans>
</ThemedText.Black>
<HelpTooltip
text={
<Trans>
Allows you to approve a token for a specific amount, rather than the maximum amount.
By default, token approvals & permits are for an unlimited amount, which ensures you don't pay extra for subsequent trades.
<br />
<br />
When this setting is enabled, approvals & permits will be for the minimum amount instead of unlimited.
This incurs additional costs on every trade.
<br />
<br />
Existing approvals must be revoked manually before you can re-approve.
</Trans>
}
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { useSetAtom } from 'jotai'

import { SupportedChainId } from '@cowprotocol/cow-sdk'
import { Command } from '@cowprotocol/types'
Expand All @@ -10,7 +9,7 @@ import styled from 'styled-components/macro'

import { getNativeSlippageTooltip, getNonNativeSlippageTooltip } from 'common/utils/tradeSettingsTooltips'

import { settingsTabStateAtom } from '../../../state/settingsTabState'
import { useOpenSettingsTab } from '../../../state/settingsTabState'
import { RowStyleProps, StyledInfoIcon, StyledRowBetween, TextWrapper, TransactionText } from '../styled'

const DefaultSlippage = styled.span`
Expand Down Expand Up @@ -65,9 +64,7 @@ export function RowSlippageContent(props: RowSlippageContentProps) {
isSmartSlippageLoading,
} = props

const setSettingTabState = useSetAtom(settingsTabStateAtom)

const openSettings = () => setSettingTabState({ open: true })
const openSettings = useOpenSettingsTab()

const tooltipContent =
slippageTooltip ||
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
import { atom } from 'jotai'
import { atom, useSetAtom } from 'jotai'

export const settingsTabStateAtom = atom({ open: false })

export function useOpenSettingsTab() {
const setSettingTabState = useSetAtom(settingsTabStateAtom)

return () => setSettingTabState({ open: true })
}
5 changes: 4 additions & 1 deletion apps/cowswap-frontend/src/pages/Swap/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,16 @@ import { useWalletInfo } from '@cowprotocol/wallet'
import { Navigate, useLocation, useParams } from 'react-router-dom'

import { SwapUpdaters, SwapWidget } from 'modules/swap'
import { PartialApprovalBanner } from 'modules/swap/pure/banners/PartialApprovalBanner'
import { getDefaultTradeRawState } from 'modules/trade/types/TradeRawState'
import { parameterizeTradeRoute } from 'modules/trade/utils/parameterizeTradeRoute'
import { useOpenSettingsTab } from 'modules/tradeWidgetAddons/state/settingsTabState'

import { Routes } from 'common/constants/routes'

export function SwapPage() {
const params = useParams()
const openSettings = useOpenSettingsTab()

if (!params.chainId) {
return <SwapPageRedirect />
Expand All @@ -20,7 +23,7 @@ export function SwapPage() {
return (
<>
<SwapUpdaters />
<SwapWidget />
<SwapWidget topContent={<PartialApprovalBanner openSettings={openSettings} />} />
</>
)
}
Expand Down
2 changes: 1 addition & 1 deletion libs/ui/src/containers/InlineBanner/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { ReactNode } from 'react'
import { ReactNode } from 'react'

import { X } from 'react-feather'
import SVG from 'react-inlinesvg'
Expand Down
9 changes: 9 additions & 0 deletions libs/ui/src/pure/LinkStyledButton/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,12 @@ export const LinkStyledButton = styled.button<{ disabled?: boolean; bg?: boolean
text-decoration: none;
}
`

export const UnderlinedLinkStyledButton = styled(LinkStyledButton)`
font-size: 14px;
text-decoration: underline;
&:hover {
text-decoration: none;
}
`
Loading