ci(release): publish latest release

parent d3d40917
IPFS hash of the deployment: IPFS hash of the deployment:
- CIDv0: `Qmbj1BRiCidfqEHnayhdwiEWEwFvP7RJbH58pmw3G81PvV` - CIDv0: `QmQ7NhMzZjWwmzHeuQT8PwZCMvvAzDQrXWFCDe3Mqx414a`
- CIDv1: `bafybeigg4hnmdqhtzox3vuqnfy2pmvb6mkr5kgoubridxbe3idri7qx6qy` - CIDv1: `bafybeia2kc33gaewnivhsxglgbtpvdeo2rqwufsgkaurutq3jyxnsoygw4`
The latest release is always mirrored at [app.uniswap.org](https://app.uniswap.org). The latest release is always mirrored at [app.uniswap.org](https://app.uniswap.org).
...@@ -10,15 +10,15 @@ You can also access the Uniswap Interface from an IPFS gateway. ...@@ -10,15 +10,15 @@ You can also access the Uniswap Interface from an IPFS gateway.
Your Uniswap settings are never remembered across different URLs. Your Uniswap settings are never remembered across different URLs.
IPFS gateways: IPFS gateways:
- https://bafybeigg4hnmdqhtzox3vuqnfy2pmvb6mkr5kgoubridxbe3idri7qx6qy.ipfs.dweb.link/ - https://bafybeia2kc33gaewnivhsxglgbtpvdeo2rqwufsgkaurutq3jyxnsoygw4.ipfs.dweb.link/
- https://bafybeigg4hnmdqhtzox3vuqnfy2pmvb6mkr5kgoubridxbe3idri7qx6qy.ipfs.cf-ipfs.com/ - https://bafybeia2kc33gaewnivhsxglgbtpvdeo2rqwufsgkaurutq3jyxnsoygw4.ipfs.cf-ipfs.com/
- [ipfs://Qmbj1BRiCidfqEHnayhdwiEWEwFvP7RJbH58pmw3G81PvV/](ipfs://Qmbj1BRiCidfqEHnayhdwiEWEwFvP7RJbH58pmw3G81PvV/) - [ipfs://QmQ7NhMzZjWwmzHeuQT8PwZCMvvAzDQrXWFCDe3Mqx414a/](ipfs://QmQ7NhMzZjWwmzHeuQT8PwZCMvvAzDQrXWFCDe3Mqx414a/)
## 5.6.0 (2024-01-29) ### 5.6.1 (2024-01-30)
### Features ### Bug Fixes
* **web:** bump v2-sdk [hotfix for prod] (#5987) 22b73de * **web:** send flow UI fixes [hotfix] (#6026) cbffa89
web/5.6.0 web/5.6.1
\ No newline at end of file \ No newline at end of file
...@@ -8,44 +8,56 @@ import { ReverseArrow } from 'components/Icons/ReverseArrow' ...@@ -8,44 +8,56 @@ import { ReverseArrow } from 'components/Icons/ReverseArrow'
import { LoadingOpacityContainer } from 'components/Loader/styled' import { LoadingOpacityContainer } from 'components/Loader/styled'
import { Input as NumericalInput } from 'components/NumericalInput' import { Input as NumericalInput } from 'components/NumericalInput'
import PrefetchBalancesWrapper from 'components/PrefetchBalancesWrapper/PrefetchBalancesWrapper' import PrefetchBalancesWrapper from 'components/PrefetchBalancesWrapper/PrefetchBalancesWrapper'
import Row from 'components/Row' import Row, { RowBetween } from 'components/Row'
import CurrencySearchModal from 'components/SearchModal/CurrencySearchModal' import CurrencySearchModal from 'components/SearchModal/CurrencySearchModal'
import { useActiveLocalCurrency, useActiveLocalCurrencyComponents } from 'hooks/useActiveLocalCurrency' import { useActiveLocalCurrency, useActiveLocalCurrencyComponents } from 'hooks/useActiveLocalCurrency'
import { STABLECOIN_AMOUNT_OUT } from 'hooks/useStablecoinPrice' import { STABLECOIN_AMOUNT_OUT } from 'hooks/useStablecoinPrice'
import { useUSDPrice } from 'hooks/useUSDPrice'
import { useCallback, useMemo, useState } from 'react' import { useCallback, useMemo, useState } from 'react'
import { SendInputError } from 'state/send/hooks' import { SendInputError } from 'state/send/hooks'
import { useSendContext } from 'state/send/SendContext' import { useSendContext } from 'state/send/SendContext'
import { CurrencyState, useSwapAndLimitContext } from 'state/swap/SwapContext' import { CurrencyState, useSwapAndLimitContext } from 'state/swap/SwapContext'
import styled, { css } from 'styled-components' import styled, { css } from 'styled-components'
import { ClickableStyle, CloseIcon, ThemedText } from 'theme/components' import { ClickableStyle, ThemedText } from 'theme/components'
import { NumberType, useFormatter } from 'utils/formatNumbers' import { NumberType, useFormatter } from 'utils/formatNumbers'
import { maxAmountSpend } from 'utils/maxAmountSpend' import { maxAmountSpend } from 'utils/maxAmountSpend'
import { ReactComponent as DropDown } from '../../../assets/images/dropdown.svg'
const Wrapper = styled(Column)<{ $disabled: boolean }>` const Wrapper = styled(Column)<{ $disabled: boolean }>`
opacity: ${({ $disabled }) => (!$disabled ? 1 : 0.4)}; opacity: ${({ $disabled }) => (!$disabled ? 1 : 0.4)};
pointer-events: ${({ $disabled }) => (!$disabled ? 'initial' : 'none')}; pointer-events: ${({ $disabled }) => (!$disabled ? 'initial' : 'none')};
gap: 1px;
` `
const CurrencyInputWrapper = styled(PrefetchBalancesWrapper)` const CurrencyInputWrapper = styled(PrefetchBalancesWrapper)`
display: flex; display: flex;
background-color: ${({ theme }) => theme.surface2}; background-color: ${({ theme }) => theme.surface2};
padding: 14px 12px; padding: 16px 16px;
border-radius: 16px 16px 0px 0px; border-radius: 0px 0px 16px 16px;
height: 64px; height: 64px;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
border-bottom: 1px solid ${({ theme }) => theme.surface1}; position: relative;
`
const ClickableRowBetween = styled(RowBetween)`
${ClickableStyle};
` `
const InputWrapper = styled(Column)` const InputWrapper = styled(Column)`
position: relative; position: relative;
background-color: ${({ theme }) => theme.surface2}; background-color: ${({ theme }) => theme.surface2};
padding: 0px 12px; padding: 0px 12px 60px 12px;
height: 220px; height: 256px;
align-items: center; align-items: center;
justify-content: center; justify-content: flex-end;
gap: 16px; gap: 16px;
border-radius: 0px 0px 16px 16px; border-radius: 16px 16px 0px 0px;
`
const InputLabelContainer = styled.div`
position: absolute;
top: 16px;
left: 16px;
` `
const StyledNumericalInput = styled(NumericalInput)<{ usePercent?: boolean }>` const StyledNumericalInput = styled(NumericalInput)<{ usePercent?: boolean }>`
...@@ -65,16 +77,22 @@ const StyledUpAndDownArrowIcon = styled(ReverseArrow)` ...@@ -65,16 +77,22 @@ const StyledUpAndDownArrowIcon = styled(ReverseArrow)`
` `
const MaxButton = styled(ButtonLight)` const MaxButton = styled(ButtonLight)`
position: absolute;
right: 40px;
height: min-content; height: min-content;
width: min-content; width: min-content;
padding: 2px 8px; padding: 2px 8px;
font-size: 14px; font-size: 14px;
line-height: 20px; line-height: 20px;
` `
const StyledDropDown = styled(DropDown)`
const StyledCloseIcon = styled(CloseIcon)`
color: ${({ theme }) => theme.neutral3};
${ClickableStyle} ${ClickableStyle}
width: 20px;
height: 8px;
path {
stroke: ${({ theme }) => theme.neutral3};
stroke-width: 2px;
}
` `
const CurrencySelectorRow = styled(Row)` const CurrencySelectorRow = styled(Row)`
...@@ -177,6 +195,7 @@ export default function SendCurrencyInputForm({ ...@@ -177,6 +195,7 @@ export default function SendCurrencyInputForm({
const { account } = useWeb3React() const { account } = useWeb3React()
const { formatCurrencyAmount } = useFormatter() const { formatCurrencyAmount } = useFormatter()
const { symbol: fiatSymbol } = useActiveLocalCurrencyComponents() const { symbol: fiatSymbol } = useActiveLocalCurrencyComponents()
const { formatNumber } = useFormatter()
const { sendState, setSendState, derivedSendInfo } = useSendContext() const { sendState, setSendState, derivedSendInfo } = useSendContext()
const { inputInFiat, exactAmountToken, exactAmountFiat, inputCurrency } = sendState const { inputInFiat, exactAmountToken, exactAmountFiat, inputCurrency } = sendState
...@@ -193,6 +212,8 @@ export default function SendCurrencyInputForm({ ...@@ -193,6 +212,8 @@ export default function SendCurrencyInputForm({
type: NumberType.TokenNonTx, type: NumberType.TokenNonTx,
}) })
const fiatBalanceValue = useUSDPrice(currencyBalance, inputCurrency)
const handleUserInput = useCallback( const handleUserInput = useCallback(
(newValue: string) => { (newValue: string) => {
setSendState((prev) => ({ setSendState((prev) => ({
...@@ -257,30 +278,12 @@ export default function SendCurrencyInputForm({ ...@@ -257,30 +278,12 @@ export default function SendCurrencyInputForm({
return ( return (
<Wrapper $disabled={disabled}> <Wrapper $disabled={disabled}>
<CurrencyInputWrapper shouldFetchOnAccountUpdate={tokenSelectorOpen}>
<Row justify="space-between" width="100%" gap="sm">
<Row width="100%" gap="md">
<CurrencySelectorRow width="100%" gap="md" onClick={() => setTokenSelectorOpen(true)}>
{inputCurrency && (
<PortfolioLogo currencies={[inputCurrency]} size="36px" chainId={chainId ?? ChainId.MAINNET} />
)}
<Row width="100%">
<Column>
<ThemedText.BodyPrimary lineHeight="24px">{inputCurrency?.name}</ThemedText.BodyPrimary>
<ThemedText.LabelMicro lineHeight="16px">{currencyBalance && formattedBalance}</ThemedText.LabelMicro>
</Column>
</Row>
</CurrencySelectorRow>
{showMaxButton && (
<MaxButton onClick={handleMaxInput}>
<Trans>Max</Trans>
</MaxButton>
)}
</Row>
<StyledCloseIcon size="20px" onClick={() => setTokenSelectorOpen(true)} />
</Row>
</CurrencyInputWrapper>
<InputWrapper> <InputWrapper>
<InputLabelContainer>
<ThemedText.SubHeaderSmall color="neutral2">
<Trans>You&apos;re sending</Trans>
</ThemedText.SubHeaderSmall>
</InputLabelContainer>
<StyledNumericalInput <StyledNumericalInput
value={inputInFiat ? exactAmountFiat : exactAmountToken} value={inputInFiat ? exactAmountFiat : exactAmountToken}
disabled={disabled} disabled={disabled}
...@@ -294,6 +297,41 @@ export default function SendCurrencyInputForm({ ...@@ -294,6 +297,41 @@ export default function SendCurrencyInputForm({
/> />
<InputError /> <InputError />
</InputWrapper> </InputWrapper>
<CurrencyInputWrapper shouldFetchOnAccountUpdate={tokenSelectorOpen}>
<ClickableRowBetween onClick={() => setTokenSelectorOpen(true)}>
<Row width="100%" gap="md">
<CurrencySelectorRow width="100%" gap="md" onClick={() => setTokenSelectorOpen(true)}>
{inputCurrency && (
<PortfolioLogo currencies={[inputCurrency]} size="36px" chainId={chainId ?? ChainId.MAINNET} />
)}
<Row width="100%">
<Column>
<ThemedText.BodyPrimary lineHeight="24px">
{inputCurrency?.symbol ?? inputCurrency?.name}
</ThemedText.BodyPrimary>
<Row gap="xs" width="100%">
{currencyBalance && (
<ThemedText.LabelMicro lineHeight="16px">{`Balance: ${formattedBalance}`}</ThemedText.LabelMicro>
)}
{Boolean(fiatBalanceValue.data) && (
<ThemedText.LabelMicro lineHeight="16px" color="neutral3">{`(${formatNumber({
input: fiatBalanceValue.data,
type: NumberType.FiatTokenPrice,
})})`}</ThemedText.LabelMicro>
)}
</Row>
</Column>
</Row>
</CurrencySelectorRow>
</Row>
<StyledDropDown />
</ClickableRowBetween>
{showMaxButton && (
<MaxButton onClick={handleMaxInput}>
<Trans>Max</Trans>
</MaxButton>
)}
</CurrencyInputWrapper>
<CurrencySearchModal <CurrencySearchModal
isOpen={tokenSelectorOpen} isOpen={tokenSelectorOpen}
onDismiss={() => setTokenSelectorOpen(false)} onDismiss={() => setTokenSelectorOpen(false)}
......
...@@ -35,7 +35,7 @@ const RecipientWrapper = styled(Column)<{ $disabled?: boolean }>` ...@@ -35,7 +35,7 @@ const RecipientWrapper = styled(Column)<{ $disabled?: boolean }>`
position: relative; position: relative;
background-color: ${({ theme }) => theme.surface2}; background-color: ${({ theme }) => theme.surface2};
border-radius: 16px; border-radius: 16px;
padding: 12px; padding: 12px 16px;
gap: 4px; gap: 4px;
opacity: ${({ $disabled }) => (!$disabled ? 1 : 0.4)}; opacity: ${({ $disabled }) => (!$disabled ? 1 : 0.4)};
pointer-events: ${({ $disabled }) => (!$disabled ? 'initial' : 'none')}; pointer-events: ${({ $disabled }) => (!$disabled ? 'initial' : 'none')};
...@@ -279,9 +279,9 @@ export function SendRecipientForm({ disabled }: { disabled?: boolean }) { ...@@ -279,9 +279,9 @@ export function SendRecipientForm({ disabled }: { disabled?: boolean }) {
<RecipientWrapper $disabled={disabled}> <RecipientWrapper $disabled={disabled}>
{showInputField ? ( {showInputField ? (
<> <>
<ThemedText.BodySecondary lineHeight="24px"> <ThemedText.SubHeaderSmall lineHeight="24px">
<Trans>To</Trans> <Trans>To</Trans>
</ThemedText.BodySecondary> </ThemedText.SubHeaderSmall>
<StyledRecipientInputRow justify="space-between"> <StyledRecipientInputRow justify="space-between">
<Row ref={inputWrapperNode}> <Row ref={inputWrapperNode}>
<StyledRecipientInput <StyledRecipientInput
......
...@@ -86,13 +86,19 @@ export function SendReviewModal({ onConfirm, onDismiss }: { onConfirm: () => voi ...@@ -86,13 +86,19 @@ export function SendReviewModal({ onConfirm, onDismiss }: { onConfirm: () => voi
type: NumberType.PortfolioBalance, type: NumberType.PortfolioBalance,
}) })
const currencySymbolAmount = `${formattedInputAmount} ${inputCurrency?.symbol ?? inputCurrency?.name}`
const [primaryInputView, secondaryInputView] = inputInFiat
? [formattedFiatInputAmount, currencySymbolAmount]
: [currencySymbolAmount, formattedFiatInputAmount]
return ( return (
<Modal $scrollOverlay isOpen onDismiss={onDismiss} maxHeight={90}> <Modal $scrollOverlay isOpen onDismiss={onDismiss} maxHeight={90}>
<ModalWrapper gap="md"> <ModalWrapper gap="md">
<Row width="100%" padding="8px 12px 4px" align="center"> <Row width="100%" padding="8px 12px 4px" align="center">
<Row justify="left"> <Row justify="left">
<ThemedText.SubHeader> <ThemedText.SubHeader>
<Trans>Review swap</Trans> <Trans>Review send</Trans>
</ThemedText.SubHeader> </ThemedText.SubHeader>
</Row> </Row>
<Row justify="right" gap="10px"> <Row justify="right" gap="10px">
...@@ -104,8 +110,8 @@ export function SendReviewModal({ onConfirm, onDismiss }: { onConfirm: () => voi ...@@ -104,8 +110,8 @@ export function SendReviewModal({ onConfirm, onDismiss }: { onConfirm: () => voi
<Column gap="lg"> <Column gap="lg">
<SendModalHeader <SendModalHeader
label={<Trans>You&apos;re sending</Trans>} label={<Trans>You&apos;re sending</Trans>}
header={formattedFiatInputAmount} header={primaryInputView}
subheader={formattedInputAmount + ' ' + inputCurrency?.symbol} subheader={secondaryInputView}
image={<PortfolioLogo currencies={[inputCurrency]} size="36px" chainId={chainId ?? ChainId.MAINNET} />} image={<PortfolioLogo currencies={[inputCurrency]} size="36px" chainId={chainId ?? ChainId.MAINNET} />}
/> />
<SendModalHeader <SendModalHeader
...@@ -138,7 +144,9 @@ export function SendReviewModal({ onConfirm, onDismiss }: { onConfirm: () => voi ...@@ -138,7 +144,9 @@ export function SendReviewModal({ onConfirm, onDismiss }: { onConfirm: () => voi
</Row> </Row>
</Row> </Row>
</ReviewContentContainer> </ReviewContentContainer>
<ButtonPrimary onClick={onConfirm}>Confirm send</ButtonPrimary> <ButtonPrimary onClick={onConfirm}>
<Trans>Confirm send</Trans>
</ButtonPrimary>
</ModalWrapper> </ModalWrapper>
</Modal> </Modal>
) )
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment