diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 65dc853d..1bb6af2d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -375,6 +375,9 @@ importers: '@fontsource-variable/figtree': specifier: ^5.0.20 version: 5.1.1 + '@fontsource-variable/inter': + specifier: ^5.2.8 + version: 5.2.8 '@fontsource-variable/roboto-mono': specifier: ^5.0.18 version: 5.1.0 @@ -457,6 +460,9 @@ importers: bignumber.js: specifier: ^9.1.2 version: 9.1.2 + lucide-react: + specifier: ^0.513.0 + version: 0.513.0(react@18.3.1) react: specifier: ^18.2.0 version: 18.3.1 diff --git a/ui/package.json b/ui/package.json index 8a2bfd69..22463090 100644 --- a/ui/package.json +++ b/ui/package.json @@ -16,6 +16,7 @@ "dependencies": { "@floating-ui/react": "^0.26.24", "@fontsource-variable/figtree": "^5.0.20", + "@fontsource-variable/inter": "^5.2.8", "@fontsource-variable/roboto-mono": "^5.0.18", "@material-design-icons/svg": "^0.14.13", "@metamask/jazzicon": "^2.0.0", diff --git a/ui/src/core/components/AppLayout/index.tsx b/ui/src/core/components/AppLayout/index.tsx index cca58f0f..4487f008 100644 --- a/ui/src/core/components/AppLayout/index.tsx +++ b/ui/src/core/components/AppLayout/index.tsx @@ -55,6 +55,7 @@ export const AppLayout = () => { return ( diff --git a/ui/src/core/index.css b/ui/src/core/index.css index 4e5bb3c9..adcb480a 100644 --- a/ui/src/core/index.css +++ b/ui/src/core/index.css @@ -1,5 +1,6 @@ @import '@fontsource-variable/figtree/index.css'; @import '@fontsource-variable/roboto-mono/index.css'; +@import '@fontsource-variable/inter'; /** Use Figtree for "…" instead of Roboto Mono. */ @font-face { @@ -12,6 +13,7 @@ } :root { + --default-font-family: 'Inter Variable', sans-serif; --black: #000; --blue-bg: #3902e1; --blue-dark-border: #1b0f33; @@ -62,7 +64,7 @@ body { margin: 0; - font-family: 'Figtree Variable', system-ui, sans-serif; + font-family: 'Inter Variable', sans-serif; font-size: 16px; font-style: normal; font-weight: normal; diff --git a/ui/src/wrap/components/index.ts b/ui/src/wrap/components/index.ts index 8c0753d2..70e1bbdd 100644 --- a/ui/src/wrap/components/index.ts +++ b/ui/src/wrap/components/index.ts @@ -2,7 +2,6 @@ export { Alert as WrapAlert } from './Alert' export { Button as WrapButton } from './Button' export * from './icons' export { Input as WrapInput } from './Input' -export { Layout as WrapLayout } from './Layout' export { Modal as WrapModal } from './Modal' export * from './Spinner' export { ToggleButton as WrapToggleButton } from './ToggleButton' diff --git a/wrap/package.json b/wrap/package.json index 1d43104d..c2d9d696 100644 --- a/wrap/package.json +++ b/wrap/package.json @@ -21,6 +21,7 @@ "@oasisprotocol/ui-library": "file:../ui-library", "@rainbow-me/rainbowkit": "^2.1.2", "bignumber.js": "^9.1.2", + "lucide-react": "^0.513.0", "react": "^18.2.0", "react-responsive": "^9.0.2", "react-router-dom": "^6.22.2", diff --git a/wrap/src/App.tsx b/wrap/src/App.tsx index e93fd0ab..4ad3fc20 100644 --- a/wrap/src/App.tsx +++ b/wrap/src/App.tsx @@ -1,9 +1,11 @@ import { FC } from 'react' -import { WrapLayout } from '@oasisprotocol/rose-app-ui/wrap' +import { Outlet } from 'react-router-dom' import { Web3ContextProvider } from './providers/Web3Provider' export const App: FC = () => ( - +
+ +
) diff --git a/wrap/src/components/WrapFeeWarningModal/index.module.css b/wrap/src/components/WrapFeeWarningModal/index.module.css deleted file mode 100644 index ffc18ba5..00000000 --- a/wrap/src/components/WrapFeeWarningModal/index.module.css +++ /dev/null @@ -1,83 +0,0 @@ -.wrapFeeWarningModalContent { - display: flex; - flex-direction: column; - - h4 { - color: var(--gray-wrap-extra-dark); - } - - p { - color: var(--gray-wrap-extra-dark); - - &:first-of-type { - margin-bottom: 1rem; - } - - &:last-of-type { - margin-bottom: 3.125rem; - } - } -} - -.wrapFeeWarningModalLogo { - align-self: center; - margin-bottom: 3.125rem; -} - -.wrapFeeWarningModalInput { - width: 75%; - margin: 0 auto; -} - -.wrapFeeWarningModalActions { - display: flex; - flex-direction: column; - gap: 2.125rem; - margin: 2.5rem auto; - text-align: center; -} - -.wrapFeeWarningModalButton { - min-width: 250px; -} - -.wrapFeeWarningModalButtonText { - font-size: 13px; -} - -.wrapFeeWarningModalFullAmount { - background: none; - border: none; - padding: 0; - font: inherit; - outline: inherit; - color: var(--danger); - text-decoration: underline; - cursor: pointer; -} - -@media screen and (max-width: 1000px) { - .wrapFeeWarningModalContent { - p { - &:last-of-type { - margin-bottom: 2.625rem; - } - } - } - - .wrapFeeWarningModalLogo { - margin-bottom: 2rem; - } - - .wrapFeeWarningModalInput { - width: 100%; - } - - .wrapFeeWarningModalActions { - display: flex; - flex-direction: column; - gap: 1.625rem; - margin: 1.25rem auto; - text-align: center; - } -} diff --git a/wrap/src/components/WrapFeeWarningModal/index.tsx b/wrap/src/components/WrapFeeWarningModal/index.tsx index ab9ef94d..7fd1da3c 100644 --- a/wrap/src/components/WrapFeeWarningModal/index.tsx +++ b/wrap/src/components/WrapFeeWarningModal/index.tsx @@ -1,19 +1,28 @@ import { FC } from 'react' -import { - WrapModal, - WrapModalProps, - LogoIconRound, - WrapInput, - WrapButton, -} from '@oasisprotocol/rose-app-ui/wrap' -import classes from './index.module.css' import { useWrapForm } from '../../hooks/useWrapForm' import { WRAP_FEE_DEDUCTION_MULTIPLIER } from '../../constants/config' import { NumberUtils } from '../../utils/number.utils' import BigNumber from 'bignumber.js' import { formatEther } from 'viem' +import { Button } from '@oasisprotocol/ui-library/src/components/button' +import { + Dialog, + DialogClose, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from '@oasisprotocol/ui-library/src/components/dialog' +import { + InputGroup, + InputGroupAddon, + InputGroupInput, +} from '@oasisprotocol/ui-library/src/components/ui/input-group' // TODO: fix import path in UIL -interface WrapFeeWarningModalProps extends Pick { +interface WrapFeeWarningModalProps { + isOpen: boolean + closeModal: () => void next: (amount: BigNumber) => void } @@ -22,52 +31,59 @@ export const WrapFeeWarningModal: FC = ({ isOpen, clos state: { amount, estimatedFee }, } = useWrapForm() const estimatedFeeDeduction = estimatedFee.multipliedBy(WRAP_FEE_DEDUCTION_MULTIPLIER) - const roseAmount = NumberUtils.ensureNonNullBigNumber(amount) const estimatedAmountWithDeductedFees = roseAmount!.minus(estimatedFeeDeduction) return ( - -
-
- -
+ + + + You have chosen to wrap your entire balance + + + It is recommended to keep a small amount in your wallet at all times to cover future + transactions. + + + Choose if you want to wrap the reduced amount and keep {sum of{' '} + {WRAP_FEE_DEDUCTION_MULTIPLIER} x gas fee - e.g. ‘ + {formatEther(NumberUtils.BNtoBigInt(estimatedFeeDeduction))} ROSE’} in your account, + or continue with the full amount. + + + -

You have chosen to wrap your entire balance

- -

- It is recommended to keep a small amount in your wallet at all times to cover future transactions. -

-

- Choose if you want to wrap the reduced amount and keep {sum of {WRAP_FEE_DEDUCTION_MULTIPLIER}{' '} - x gas fee - e.g. ‘{formatEther(NumberUtils.BNtoBigInt(estimatedFeeDeduction))} ROSE’} in - your account, or continue with the full amount. -

- - - className={classes.wrapFeeWarningModalInput} - variant="dark" - disabled - type="text" - label="wROSE" - placeholder="0" - inputMode="decimal" - value={formatEther(NumberUtils.BNtoBigInt(estimatedAmountWithDeductedFees))} - /> - -
- next(estimatedAmountWithDeductedFees)} - > - Wrap reduced amount - - - +
+
+ + + + wROSE + + +
-
- + + + + + + + + + +
+
) } diff --git a/wrap/src/components/WrapForm/index.module.css b/wrap/src/components/WrapForm/index.module.css deleted file mode 100644 index d64403a2..00000000 --- a/wrap/src/components/WrapForm/index.module.css +++ /dev/null @@ -1,36 +0,0 @@ -.wrapForm { - display: flex; - flex-direction: column; - position: relative; -} - -.wrapFormInputs { - position: relative; - display: flex; - flex-direction: column; - gap: 0.625rem; -} - -.toggleBtn { - position: absolute; - left: 2.8125rem; - top: 50%; - transform: translateY(-50%); -} - -.gasEstimateLabel.gasEstimateLabel { - text-align: center; - margin: 2rem 0 1rem; -} - -@media screen and (min-width: 1000px) { - .toggleBtn { - left: 50%; - top: 50%; - transform: translate3d(-50%, -50%, 0); - } - - .gasEstimateLabel { - margin: 3.875rem 0 1.5rem; - } -} diff --git a/wrap/src/components/WrapForm/index.tsx b/wrap/src/components/WrapForm/index.tsx index 06fe149b..b8d943cd 100644 --- a/wrap/src/components/WrapForm/index.tsx +++ b/wrap/src/components/WrapForm/index.tsx @@ -1,6 +1,4 @@ import { FC, FormEvent, MouseEvent, useEffect, useRef, useState } from 'react' -import { WrapInput, WrapButton, WrapAlert, WrapToggleButton } from '@oasisprotocol/rose-app-ui/wrap' -import classes from './index.module.css' import { useNavigate } from 'react-router-dom' import { useWrapForm } from '../../hooks/useWrapForm' import { WrapFormType } from '../../utils/types' @@ -9,6 +7,16 @@ import { NumberUtils } from '../../utils/number.utils' import { WrapFeeWarningModal } from '../WrapFeeWarningModal' import { BaseError, formatEther, parseEther } from 'viem' import BigNumber from 'bignumber.js' +import { + InputGroup, + InputGroupAddon, + InputGroupButton, + InputGroupInput, +} from '@oasisprotocol/ui-library/src/components/ui/input-group' // TODO: fix import path in UIL +import { Button } from '@oasisprotocol/ui-library/src/components/button' +import { ArrowUpDown } from 'lucide-react' +import { Separator } from '@oasisprotocol/ui-library/src/components/separator' +import { Label } from '@oasisprotocol/ui-library/src/components/label' const AMOUNT_PATTERN = '^[0-9]*[.,]?[0-9]*$' @@ -34,8 +42,9 @@ const labelMapByFormType: Record = { export const WrapForm: FC = () => { const navigate = useNavigate() const { - state: { formType, amount, isLoading, balance, estimatedFee }, + state: { formType, amount, isLoading, balance, estimatedFee, wRoseBalance }, toggleFormType, + setAmount, submit, debounceLeadingSetFeeAmount, } = useWrapForm() @@ -118,43 +127,105 @@ export const WrapForm: FC = () => { const estimatedFeeTruncated = estimatedFee && estimatedFee.gt(0) ? `~${NumberUtils.getTruncatedAmount(estimatedFee)} ROSE` : '/' + const handlePercentageCalc = () => { + const percentage = BigNumber(100) + if (formType === WrapFormType.WRAP) { + /* In case of 100% WRAP, deduct gas fee */ + const percAmount = NumberUtils.getPercentageAmount(balance, percentage) + setAmount(percAmount.minus(estimatedFee)) + } else if (formType === WrapFormType.UNWRAP) { + setAmount(NumberUtils.getPercentageAmount(wRoseBalance, percentage)) + } else { + throw new Error('[formType] Invalid form type') + } + } + return (
-
-
- - disabled={isLoading} - type="text" - label={firstInputLabel} - pattern={AMOUNT_PATTERN} - placeholder="0" - inputMode="decimal" - value={value} - valueChange={handleValueChange} - /> - - disabled={isLoading} - type="text" - label={secondInputLabel} - pattern={AMOUNT_PATTERN} - placeholder="0" - inputMode="decimal" - value={value} - valueChange={handleValueChange} - /> - + +
+
+ + + + + + Max + + {firstInputLabel} + + + + Balance: {formType === WrapFormType.WRAP && NumberUtils.getTruncatedAmount(balance)} + {formType === WrapFormType.UNWRAP && NumberUtils.getTruncatedAmount(wRoseBalance)}{' '} + {firstInputLabel} + +
+ +
+ + + +
+ +
+ + + + + + Max + + {secondInputLabel} + + + + Balance: {formType === WrapFormType.WRAP && NumberUtils.getTruncatedAmount(wRoseBalance)} + {formType === WrapFormType.UNWRAP && NumberUtils.getTruncatedAmount(balance)} {secondInputLabel} + +
-

Estimated fee: {estimatedFeeTruncated}

+
+ Estimated gas fee: + {estimatedFeeTruncated} +
- + + + {error &&

{error}

} { return ( -
- - -

- Quickly wrap your ROSE into wROSE and vice versa with the (un)wrap ROSE tool. -
- Please connect your wallet to get started. -

- - -
+ + + Wrap + + Quickly wrap your ROSE into wROSE and vice versa with the (un)wrap ROSE tool. Please connect your + wallet to get started. + + + + + + ) } diff --git a/wrap/src/pages/Transaction/index.module.css b/wrap/src/pages/Transaction/index.module.css deleted file mode 100644 index ffba4f55..00000000 --- a/wrap/src/pages/Transaction/index.module.css +++ /dev/null @@ -1,35 +0,0 @@ -.noUnderlineLink { - text-decoration: none; -} - -.openInExplorerBtn { - display: flex; - justify-content: center; - align-items: center; - gap: 0.5rem; - padding: 1.06rem 1.5rem; - margin-bottom: 1.5rem; -} - -.spinnerContainer { - margin-top: 5rem; - margin-bottom: 2.625rem; -} - -.subHeader { - text-align: center; - margin-bottom: 3.625rem; -} - -.h100 { - font-size: 75px; - font-weight: 400; - line-height: 150%; - text-align: center; -} - -@media screen and (min-width: 1000px) { - .spinnerContainer { - margin-top: unset; - } -} diff --git a/wrap/src/pages/Transaction/index.tsx b/wrap/src/pages/Transaction/index.tsx index fe7215f2..3815deb9 100644 --- a/wrap/src/pages/Transaction/index.tsx +++ b/wrap/src/pages/Transaction/index.tsx @@ -1,12 +1,14 @@ import { FC, useEffect, useState } from 'react' -import { WrapButton, OpenInNewIcon, Spinner } from '@oasisprotocol/rose-app-ui/wrap' import { useNavigate, useParams, useSearchParams } from 'react-router-dom' -import classes from './index.module.css' import { StringUtils } from '../../utils/string.utils' import { useWeb3 } from '../../hooks/useWeb3' import { WrapFormType } from '../../utils/types' import { TransactionBase } from 'viem' import { withDisconnectedWallet } from '../../hoc/withDisconnectedWallet' +import { Button } from '@oasisprotocol/ui-library/src/components/button' +import { Typography } from '@oasisprotocol/ui-library/src/components/typography' +import { ExternalLink } from 'lucide-react' +import { cn } from '@oasisprotocol/ui-library/src/lib/utils' enum TransactionStatus { Loading, @@ -63,58 +65,62 @@ const TransactionCmp: FC = () => { } return ( - <> +
+
+ {/* mitigate webm black background */} + +
{status === TransactionStatus.Loading && ( -
-
- -
-

- {action === WrapFormType.WRAP && <>Wrapping} - {action === WrapFormType.UNWRAP && <>Unwrapping} -  your tokens -

-
+ + {action === WrapFormType.WRAP && <>Wrapping} + {action === WrapFormType.UNWRAP && <>Unwrapping} +  your tokens + )} {status === TransactionStatus.Success && ( -
-

🎉

-

- Congrats! -
- You received - {type === TransactionType.WRose &&  {amount} WROSE} - {type === TransactionType.Rose &&  {amount} ROSE} -

- - {txUrl && ( - - - View on explorer - - - - )} - - Close - +
+
+ Token Wrap Successful + + You have received {type === TransactionType.WRose && {amount} WROSE} + {type === TransactionType.Rose && {amount} ROSE} + +
+
+ + {txUrl && ( + + )} +
)} {status === TransactionStatus.Fail && ( -
-

-

- There was an unexpected error. -
- Please try again. -

- - +
+
+ Token Wrap Failed + + There was an unexpected error. Please try again. + +
+
)} - +
) } diff --git a/wrap/src/pages/Wrapper/index.module.css b/wrap/src/pages/Wrapper/index.module.css deleted file mode 100644 index 01ee65c5..00000000 --- a/wrap/src/pages/Wrapper/index.module.css +++ /dev/null @@ -1,41 +0,0 @@ -.subHeader { - display: flex; - flex-direction: column; - gap: 0.5rem; - margin-bottom: 1.5rem; -} - -.amountPercList { - display: flex; - flex-wrap: wrap; - justify-content: space-between; - margin-bottom: 1.625rem; -} - -.importWRoseBtn.importWRoseBtn { - display: flex; - justify-content: center; - padding: 0.5rem; - font-size: 14px; - font-style: normal; - font-weight: 700; - text-transform: none; - border-radius: 10px; -} - -@media screen and (min-width: 1000px) { - .subHeader { - gap: 1rem; - margin-bottom: 4.85rem; - } - - .importWRoseBtn.importWRoseBtn { - justify-content: flex-end; - margin-left: auto; - } - - .amountPercList { - width: 75%; - margin: 0 auto 1.5rem; - } -} diff --git a/wrap/src/pages/Wrapper/index.tsx b/wrap/src/pages/Wrapper/index.tsx index c5f2ce79..41a4c8f0 100644 --- a/wrap/src/pages/Wrapper/index.tsx +++ b/wrap/src/pages/Wrapper/index.tsx @@ -1,46 +1,16 @@ import { FC, useEffect } from 'react' -import classes from './index.module.css' -import { WrapButton } from '@oasisprotocol/rose-app-ui/wrap' -import { NumberUtils } from '../../utils/number.utils' import { WrapForm } from '../../components/WrapForm' -import { useWeb3 } from '../../hooks/useWeb3' import { useWrapForm } from '../../hooks/useWrapForm' import { WrapFormType } from '../../utils/types' -import BigNumber from 'bignumber.js' import { useAccount } from 'wagmi' import { withDisconnectedWallet } from '../../hoc/withDisconnectedWallet' - -interface PercentageEntry { - value: BigNumber - label: string -} - -const percentageList: PercentageEntry[] = [ - { - label: '10%', - value: BigNumber(10), - }, - { - label: '25%', - value: BigNumber(25), - }, - { - label: '50%', - value: BigNumber(50), - }, - { - label: 'Max', - value: BigNumber(100), - }, -] +import { Card, CardHeader, CardDescription, CardTitle } from '@oasisprotocol/ui-library/src/components/card' const WrapperCmp: FC = () => { const { address } = useAccount() - const { addTokenToWallet } = useWeb3() const { - state: { isLoading, balance, wRoseBalance, formType, estimatedFee }, + state: { formType }, init, - setAmount, } = useWrapForm() useEffect(() => { @@ -48,47 +18,19 @@ const WrapperCmp: FC = () => { // eslint-disable-next-line react-hooks/exhaustive-deps }, [address]) - const handlePercentageCalc = (percentage: BigNumber) => { - if (formType === WrapFormType.WRAP) { - if (percentage.eq(100)) { - /* In case of 100% WRAP, deduct gas fee */ - const percAmount = NumberUtils.getPercentageAmount(balance, percentage) - setAmount(percAmount.minus(estimatedFee)) - } else { - setAmount(NumberUtils.getPercentageAmount(balance, percentage)) - } - } else if (formType === WrapFormType.UNWRAP) { - setAmount(NumberUtils.getPercentageAmount(wRoseBalance, percentage)) - } else { - throw new Error('[formType] Invalid form type') - } - } - return ( -
-
-

Quickly wrap your ROSE into wROSE and vice versa with the (un)wrap ROSE tool.

- - - Import WROSE to Wallet - -
- -
- {percentageList.map(({ label, value }) => ( - handlePercentageCalc(value)} - key={label} - variant="tertiary" - > - {label} - - ))} -
- - -
+ + + + {formType === WrapFormType.WRAP && 'Wrap'} + {formType === WrapFormType.UNWRAP && 'Unwrap'} + + + Quickly wrap your ROSE into wROSE and vice versa with the (un)wrap ROSE tool. + + + + ) }