From 34a227895d8a6081677a51e2a1b69e7b5ca1671d Mon Sep 17 00:00:00 2001 From: Addminus Date: Thu, 17 Mar 2022 11:52:34 +0100 Subject: [PATCH] feat: transaction stepper with all states --- packages/widget/src/App.tsx | 5 + .../EmailInput/EmailInput.style.tsx | 15 + .../src/components/EmailInput/EmailInput.tsx | 79 ++++ .../widget/src/components/EmailInput/index.ts | 1 + .../NavigationHeader/NavigationHeader.tsx | 2 + packages/widget/src/components/SwapButton.tsx | 5 + .../TransactionStepper.style.tsx | 124 ++++++ .../TransactionStepper/TransactionStepper.tsx | 112 +++++ .../TransactionStepper/icons/signIcon.tsx | 27 ++ .../TransactionStepper/icons/tickIcon.tsx | 22 + .../TransactionStepper/icons/types.ts | 3 + .../components/TransactionStepper/index.ts | 1 + .../components/TransactionStepper/types.ts | 12 + packages/widget/src/i18n/en/translation.json | 25 ++ .../TransactionPage/TransactionPage.style.tsx | 24 + .../pages/TransactionPage/TransactionPage.tsx | 86 ++++ .../widget/src/pages/TransactionPage/index.ts | 2 + .../pages/TransactionPage/testRouteData.ts | 415 ++++++++++++++++++ packages/widget/src/utils/elements.ts | 1 + packages/widget/src/utils/routes.ts | 1 + 20 files changed, 962 insertions(+) create mode 100644 packages/widget/src/components/EmailInput/EmailInput.style.tsx create mode 100644 packages/widget/src/components/EmailInput/EmailInput.tsx create mode 100644 packages/widget/src/components/EmailInput/index.ts create mode 100644 packages/widget/src/components/TransactionStepper/TransactionStepper.style.tsx create mode 100644 packages/widget/src/components/TransactionStepper/TransactionStepper.tsx create mode 100644 packages/widget/src/components/TransactionStepper/icons/signIcon.tsx create mode 100644 packages/widget/src/components/TransactionStepper/icons/tickIcon.tsx create mode 100644 packages/widget/src/components/TransactionStepper/icons/types.ts create mode 100644 packages/widget/src/components/TransactionStepper/index.ts create mode 100644 packages/widget/src/components/TransactionStepper/types.ts create mode 100644 packages/widget/src/pages/TransactionPage/TransactionPage.style.tsx create mode 100644 packages/widget/src/pages/TransactionPage/TransactionPage.tsx create mode 100644 packages/widget/src/pages/TransactionPage/index.ts create mode 100644 packages/widget/src/pages/TransactionPage/testRouteData.ts diff --git a/packages/widget/src/App.tsx b/packages/widget/src/App.tsx index 6c150c0a2..6d6fa6d2c 100644 --- a/packages/widget/src/App.tsx +++ b/packages/widget/src/App.tsx @@ -9,6 +9,7 @@ import { SettingsDrawerBase } from './components/SettingsDrawer'; import { WalletHeader } from './components/WalletHeader'; import { queryClient } from './config/queryClient'; import { SwapPage } from './pages/SwapPage'; +import { TransactionPage } from './pages/TransactionPage'; import { SwapFormProvider } from './providers/SwapFormProvider'; import { WidgetProvider } from './providers/WidgetProvider'; import { theme } from './theme'; @@ -47,6 +48,10 @@ export const App: React.FC = ({ config }) => { + } + /> diff --git a/packages/widget/src/components/EmailInput/EmailInput.style.tsx b/packages/widget/src/components/EmailInput/EmailInput.style.tsx new file mode 100644 index 000000000..9e0f89481 --- /dev/null +++ b/packages/widget/src/components/EmailInput/EmailInput.style.tsx @@ -0,0 +1,15 @@ +import { styled } from '@mui/material/styles'; +import { Input as InputBase } from '../Input'; + +export const Input = styled(InputBase)({ + border: '1px solid #E4E7E9', + borderRadius: '4px', + '& input[type="number"]::-webkit-outer-spin-button, & input[type="number"]::-webkit-inner-spin-button': + { + WebkitAppearance: 'none', + margin: 0, + }, + '& input[type="number"]': { + MozAppearance: 'textfield', + }, +}); diff --git a/packages/widget/src/components/EmailInput/EmailInput.tsx b/packages/widget/src/components/EmailInput/EmailInput.tsx new file mode 100644 index 000000000..b71f9a399 --- /dev/null +++ b/packages/widget/src/components/EmailInput/EmailInput.tsx @@ -0,0 +1,79 @@ +import { Button, FormControl } from '@mui/material'; +import { Box } from '@mui/system'; +import { ChangeEvent, useEffect } from 'react'; +import { useFormContext, useWatch } from 'react-hook-form'; +import { useTranslation } from 'react-i18next'; +import { + SwapFormKeyHelper, + SwapFormTypeProps, +} from '../../providers/SwapFormProvider'; +import { formatAmount } from '../../utils/format'; +import { SwapInputAdornment } from '../SwapInputAdornment'; +import { Input } from './EmailInput.style'; + +const InputEndAdornment = () => { + return @; +}; + +export const EmailInput = () => { + const { t } = useTranslation(); + const { + register, + setValue, + formState: { isSubmitting }, + } = useFormContext(); + // const amountKey = SwapFormKeyHelper.getAmountKey(formType); + // const value = useWatch({ + // name: amountKey, + // }); + + // useEffect(() => { + // register(amountKey, { required: true }); + // }, [amountKey, register]); + + // const handleChange = ( + // event: ChangeEvent, + // ) => { + // const { value } = event.target; + // setValue(amountKey, formatAmount(value, true)); + // }; + + // const handleBlur = ( + // event: ChangeEvent, + // ) => { + // const { value } = event.target; + // setValue(amountKey, formatAmount(value)); + // }; + + return ( + :not(style)': { m: 1, width: '25ch' }, + }} + > + + } + inputProps={{ + inputMode: 'email', + }} + // onChange={handleChange} + // onBlur={handleBlur} + // value={value} + // name={amountKey} + required + /> + + {/* Text */} + + + + ); +}; diff --git a/packages/widget/src/components/EmailInput/index.ts b/packages/widget/src/components/EmailInput/index.ts new file mode 100644 index 000000000..aaa89b47f --- /dev/null +++ b/packages/widget/src/components/EmailInput/index.ts @@ -0,0 +1 @@ +export * from './EmailInput'; diff --git a/packages/widget/src/components/NavigationHeader/NavigationHeader.tsx b/packages/widget/src/components/NavigationHeader/NavigationHeader.tsx index 473ec5239..d70adfb82 100644 --- a/packages/widget/src/components/NavigationHeader/NavigationHeader.tsx +++ b/packages/widget/src/components/NavigationHeader/NavigationHeader.tsx @@ -41,6 +41,8 @@ export const NavigationHeader: React.FC = ({ return t(`swap.to`); case routes.selectWallet: return t(`header.selectWallet`); + case routes.transaction: + return t(`header.processIsOn`); default: return t(`header.swap`); } diff --git a/packages/widget/src/components/SwapButton.tsx b/packages/widget/src/components/SwapButton.tsx index 83a4f92ee..946398468 100644 --- a/packages/widget/src/components/SwapButton.tsx +++ b/packages/widget/src/components/SwapButton.tsx @@ -2,12 +2,14 @@ import { LoadingButton } from '@mui/lab'; import { styled } from '@mui/material/styles'; import { useRef } from 'react'; import { useWatch } from 'react-hook-form'; +import { useNavigate } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; import { ChainId, getChainById } from '..'; import { SwapFormKeyHelper } from '../providers/SwapFormProvider'; import { useWalletInterface } from '../services/walletInterface'; import { SelectWalletDrawer } from './SelectWalletDrawer/SelectWalletDrawer'; import { SelectWalletDrawerBase } from './SelectWalletDrawer/types'; +import { routes } from '../utils/routes'; export const Button = styled(LoadingButton)({ textTransform: 'none', @@ -16,6 +18,7 @@ export const Button = styled(LoadingButton)({ }); export const SwapButton = () => { + const navigate = useNavigate(); const { t } = useTranslation(); const { accountInformation, switchChain } = useWalletInterface(); const [chainId] = useWatch({ @@ -36,6 +39,8 @@ export const SwapButton = () => { getChainById(chainId || ChainId.ETH).id !== accountInformation.chainId ) { await switchChain(chainId!); + } else { + navigate(routes.transaction, { replace: true }); } }; diff --git a/packages/widget/src/components/TransactionStepper/TransactionStepper.style.tsx b/packages/widget/src/components/TransactionStepper/TransactionStepper.style.tsx new file mode 100644 index 000000000..d00db867b --- /dev/null +++ b/packages/widget/src/components/TransactionStepper/TransactionStepper.style.tsx @@ -0,0 +1,124 @@ +import StepConnector, { + stepConnectorClasses, +} from '@mui/material/StepConnector'; +import Step, { stepClasses } from '@mui/material/Step'; +import StepLabel, { stepLabelClasses } from '@mui/material/StepLabel'; +import { styled } from '@mui/system'; +import { StepIconProps, Theme } from '@mui/material'; +import { SignIcon } from '@lifinance/widget/components/TransactionStepper/icons/signIcon'; +import { TickIcon } from './icons/tickIcon'; + +const MIN_STEPPER_LINE_HEIGHT = 128; + +interface StepperIconBubbleOptions { + active?: boolean; + completed?: boolean; + error?: boolean; +} + +export const TransactionStep = styled(Step)(({ theme }) => ({ + position: 'relative', +})); + +export const TransactionStepLabel = styled(StepLabel)(({ theme }) => ({ + [`&.${stepLabelClasses.root}`]: { + margin: '-20px 0 -2px -3px', + padding: 0, + }, +})); + +export const TransactionStepperConnector = styled(StepConnector)( + ({ theme }) => ({ + [`&.${stepConnectorClasses.alternativeLabel}`]: {}, + [`&.${stepConnectorClasses.active}`]: { + [`& .${stepConnectorClasses.line}`]: { + background: theme.palette.primary.main, + }, + [`& .${stepConnectorClasses.line}:before`]: { + content: '" "', + position: 'absolute', + height: MIN_STEPPER_LINE_HEIGHT, + top: 0, + left: -64, + width: 64, + // background: `linear-gradient(0deg, ${theme.palette.primary.main} 0%, rgba(255,255,255,1) 100%)`, + background: `linear-gradient(0deg, ${theme.palette.primary.main} 0%, rgba(255,255,255,0) 95%)`, + opacity: 0.3, + }, + [`& .${stepConnectorClasses.line}:after`]: { + content: '" "', + position: 'absolute', + bottom: 0, + left: -64, + height: 1.5, + width: '160px', + + background: theme.palette.primary.main, + + // backgroundColor: + // theme.palette.mode === 'dark' ? theme.palette.grey[200] : '#eaeaf0', + }, + }, + [`&.${stepConnectorClasses.completed}`]: { + [`& .${stepConnectorClasses.line}`]: { + background: theme.palette.primary.main, + }, + }, + [`& .${stepConnectorClasses.line}`]: { + position: 'relative', + height: MIN_STEPPER_LINE_HEIGHT, + width: 10, + + border: 0, + backgroundColor: + theme.palette.mode === 'dark' ? theme.palette.grey[200] : '#eaeaf0', + }, + }), +); + +export const StepperIconBubble = styled('div')( + ({ + theme, + options, + }: { + theme?: Theme; + options: StepperIconBubbleOptions; + }) => ({ + display: 'flex', + justifyContent: 'center', + alignItems: 'center', + width: 40, + height: 40, + borderRadius: 30, + zIndex: 999, + boxShadow: '0px 4px 6px -8px rgba(0, 0, 0, 0.1)', + boxSizing: 'border-box', + + border: options.completed + ? '1px solid white' + : options.active + ? '2px solid #3F49E1' + : '1px solid rgba(0, 0, 0, 0.05)', + color: options.completed ? 'white' : options.active ? '#3F49E1' : 'black', + background: options.completed ? '#3F49E1' : 'white', + }), +); + +export function StepperIcons(props: StepIconProps) { + const { active, completed, error } = props; + + return ( + + + + ); +} + +export function DoneStepperIcon(props: StepIconProps) { + const { active, completed, error } = props; + return ( + + + + ); +} diff --git a/packages/widget/src/components/TransactionStepper/TransactionStepper.tsx b/packages/widget/src/components/TransactionStepper/TransactionStepper.tsx new file mode 100644 index 000000000..8038e7665 --- /dev/null +++ b/packages/widget/src/components/TransactionStepper/TransactionStepper.tsx @@ -0,0 +1,112 @@ +import { Step } from '@lifinance/sdk'; +import { Box, Button, Stepper, Typography } from '@mui/material'; +import { useState } from 'react'; +import { TFunction, useTranslation } from 'react-i18next'; +import { + TransactionStepperConnector, + TransactionStep, + TransactionStepLabel, + DoneStepperIcon, +} from './TransactionStepper.style'; +import { Props, TransactionStepperProps } from './types'; + +function capitalizeFirstLetter(string: string) { + return string.charAt(0).toUpperCase() + string.slice(1); +} + +const RouteStepLabel: React.FC = ({ + children, + active, + action, + error, +}) => { + return ( + + {children} + + ); +}; + +const LabelContent: React.FC = ({ children, active }) => { + let sx; + if (active) { + sx = { position: 'absolute', left: 158, top: -12 }; + } + return {children}; +}; + +const renderStep = ( + step: Step, + index: number, + t: TFunction<'translation', undefined>, +) => { + const isSigning = false; + const isWaiting = true; + const isFailed = false; + + const SignButton = ( + + ); + + const details = ( + + {t(`transaction.txDetails`)} + + ); + + const waitingText = ( + + 4:34 / {(step.estimate.executionDuration / 60).toFixed(0)} •{' '} + {capitalizeFirstLetter(step.tool)} + + ); + + return [ + + + + {isSigning ? SignButton : details} + + + , + + + {isWaiting ? waitingText : undefined} + + , + ]; +}; + +export const TransactionStepper: React.FC = ({ + route, +}) => { + const { t } = useTranslation(); + const [activeStep, setActiveStep] = useState(2); + + return ( + } + > + + {route.steps.map((step, index) => renderStep(step, index, t))} + + + {( + route.steps + .map((step) => step.estimate.executionDuration) + .reduce((cumulated, x) => cumulated + x) / 60 + ).toFixed(1)}{' '} + min + + + + ); +}; diff --git a/packages/widget/src/components/TransactionStepper/icons/signIcon.tsx b/packages/widget/src/components/TransactionStepper/icons/signIcon.tsx new file mode 100644 index 000000000..ccf4416d6 --- /dev/null +++ b/packages/widget/src/components/TransactionStepper/icons/signIcon.tsx @@ -0,0 +1,27 @@ +import React from 'react'; +import { IconProps } from './types'; + +export function SignIcon({ completed }: IconProps) { + console.log(completed); + + return ( + + + + + ); +} diff --git a/packages/widget/src/components/TransactionStepper/icons/tickIcon.tsx b/packages/widget/src/components/TransactionStepper/icons/tickIcon.tsx new file mode 100644 index 000000000..92a844f38 --- /dev/null +++ b/packages/widget/src/components/TransactionStepper/icons/tickIcon.tsx @@ -0,0 +1,22 @@ +import React from 'react'; +import { IconProps } from './types'; + +export function TickIcon({ completed }: IconProps) { + return ( + + + + ); +} diff --git a/packages/widget/src/components/TransactionStepper/icons/types.ts b/packages/widget/src/components/TransactionStepper/icons/types.ts new file mode 100644 index 000000000..bef0f8fb5 --- /dev/null +++ b/packages/widget/src/components/TransactionStepper/icons/types.ts @@ -0,0 +1,3 @@ +export interface IconProps { + completed?: boolean; +} diff --git a/packages/widget/src/components/TransactionStepper/index.ts b/packages/widget/src/components/TransactionStepper/index.ts new file mode 100644 index 000000000..1d6f7884c --- /dev/null +++ b/packages/widget/src/components/TransactionStepper/index.ts @@ -0,0 +1 @@ +export * from './TransactionStepper'; diff --git a/packages/widget/src/components/TransactionStepper/types.ts b/packages/widget/src/components/TransactionStepper/types.ts new file mode 100644 index 000000000..05612ed76 --- /dev/null +++ b/packages/widget/src/components/TransactionStepper/types.ts @@ -0,0 +1,12 @@ +import { Route } from '@lifinance/sdk'; + +export interface TransactionStepperProps { + route: Route; +} + +export type Props = { + children?: React.ReactNode; + active?: boolean; + action?: boolean; + error?: boolean; +}; diff --git a/packages/widget/src/i18n/en/translation.json b/packages/widget/src/i18n/en/translation.json index 7a469b40b..41facd47e 100644 --- a/packages/widget/src/i18n/en/translation.json +++ b/packages/widget/src/i18n/en/translation.json @@ -33,6 +33,31 @@ "couldntFindTokens": "We couldn't find your tokens on this chain or you don't have any.", "walletNotConnected": "Please, connect your wallet." }, + "transaction": { + "waitingTime": "Overall estimated waiting time", + "statusHeader": { + "paused": "Paused", + "errorPrompt": "Interrupted" + }, + "statusSubText": { + "paused": "Sign the transaction to continue", + "errorPrompt": "Try again or get in touch with support" + }, + "signPrompt": "Sign transaction", + "errorPrompt": "Interrupted", + "txDetails": "Details", + "footer": { + "emailForm": { + "informText": "Don’t worry, if you close your tab. We will notify you about next steps via email or browser pushes.", + "submitBtn": "Notify me", + "inputPlaceholder": "Your email" + }, + "error": { + "tryAgain": "Try again", + "support": "Support" + } + } + }, "settings": { "routePriority": { "title": "Route priority", diff --git a/packages/widget/src/pages/TransactionPage/TransactionPage.style.tsx b/packages/widget/src/pages/TransactionPage/TransactionPage.style.tsx new file mode 100644 index 000000000..d9abfbced --- /dev/null +++ b/packages/widget/src/pages/TransactionPage/TransactionPage.style.tsx @@ -0,0 +1,24 @@ +import { Box, Container } from '@mui/material'; + +import { styled } from '@mui/system'; + +export const TransactionContainer = styled(Container)({ + display: 'flex', + flexDirection: 'column', + flexGrow: 1, + position: 'relative', + background: '#FBFCFC', +}); + +export const TransactionBox = styled(Box)(({ theme }) => ({ + paddingLeft: theme.spacing(3), + paddingRight: theme.spacing(3), +})); + +export const TransactionFooter = styled(Box)(({ theme }) => ({ + width: '100%', + background: 'white', + position: 'absolute', + bottom: 0, + boxShadow: '0px 16px 64px rgba(0, 0, 0, 0.1)', +})); diff --git a/packages/widget/src/pages/TransactionPage/TransactionPage.tsx b/packages/widget/src/pages/TransactionPage/TransactionPage.tsx new file mode 100644 index 000000000..b3b169047 --- /dev/null +++ b/packages/widget/src/pages/TransactionPage/TransactionPage.tsx @@ -0,0 +1,86 @@ +import { Divider, Button, Box, Typography } from '@mui/material'; +import { useTranslation } from 'react-i18next'; +import { useSwapRoutes } from '@lifinance/widget/hooks/useSwapRoutes'; +import { useEffect, useState } from 'react'; +import { Route } from '@lifinance/sdk'; +import { TransactionStepper } from '../../components/TransactionStepper'; +import { EmailInput } from '../../components/EmailInput'; + +import { + TransactionBox, + TransactionContainer, + TransactionFooter, +} from './TransactionPage.style'; + +import { testRoutes } from './testRouteData'; + +const EmailNotificationFooter = () => { + const { t } = useTranslation(); + return ( + <> + + {t(`transaction.footer.emailForm.informText`)} + + + + ); +}; + +const ErrorFooter = () => { + const { t } = useTranslation(); + return ( + + + + + ); +}; + +export const TransactionPage = () => { + const { t } = useTranslation(); + // const { routes } = useSwapRoutes(); + const [route, setRoute] = useState(testRoutes.routes[0]); + + // useEffect(() => { + // setRoute(testRoutes.routes[0]); + // }, []); + + return ( + + + + {t(`transaction.statusHeader.paused`)} + + + {t(`transaction.statusSubText.paused`)} + + + + + + + + + + {/* */} + + + ); +}; diff --git a/packages/widget/src/pages/TransactionPage/index.ts b/packages/widget/src/pages/TransactionPage/index.ts new file mode 100644 index 000000000..b05ddfbe5 --- /dev/null +++ b/packages/widget/src/pages/TransactionPage/index.ts @@ -0,0 +1,2 @@ +export * from './TransactionPage'; +// export * from './types'; diff --git a/packages/widget/src/pages/TransactionPage/testRouteData.ts b/packages/widget/src/pages/TransactionPage/testRouteData.ts new file mode 100644 index 000000000..b0ef76380 --- /dev/null +++ b/packages/widget/src/pages/TransactionPage/testRouteData.ts @@ -0,0 +1,415 @@ +import { CoinKey, RoutesResponse } from '@lifinance/sdk'; + +export const testRoutes: RoutesResponse = { + routes: [ + { + id: '0x6ca88627d568df36d1d0d0e42964851e2fbc11e617a1db7651f5369d1dc7ff55', + fromChainId: 250, + fromAmountUSD: '1.08', + fromAmount: '1000000000000000000', + fromToken: { + address: '0x0000000000000000000000000000000000000000', + symbol: 'FTM', + decimals: 18, + chainId: 250, + name: 'FTM', + coinKey: CoinKey.FTM, + priceUSD: '1.0829', + logoURI: + 'https://static.debank.com/image/ftm_token/logo_url/ftm/33fdb9c5067e94f3a1b9e78f6fa86984.png', + }, + fromAddress: '0x552008c0f6870c2f77e5cC1d2eb9bdff03e30Ea0', + toChainId: 100, + toAmountUSD: '1.03', + toAmount: '1029578874934906550', + toAmountMin: '1029578874934906550', + toToken: { + address: '0x0000000000000000000000000000000000000000', + symbol: 'xDai', + decimals: 18, + chainId: 100, + name: 'xDai', + coinKey: CoinKey.DAI, + priceUSD: '1', + logoURI: + 'https://static.debank.com/image/xdai_token/logo_url/xdai/1207e67652b691ef3bfe04f89f4b5362.png', + }, + gasCostUSD: '0.09', + steps: [ + { + id: '0x1fe63a154d1e1e8c23395d79485d3faa84e7f8697cb36fe06d3d376dab04bc97', + type: 'lifi', + tool: 'connext', + action: { + fromChainId: 250, + fromAmount: '1000000000000000000', + fromToken: { + address: '0x0000000000000000000000000000000000000000', + symbol: 'FTM', + decimals: 18, + chainId: 250, + name: 'FTM', + coinKey: CoinKey.FTM, + priceUSD: '1.0829', + logoURI: + 'https://static.debank.com/image/ftm_token/logo_url/ftm/33fdb9c5067e94f3a1b9e78f6fa86984.png', + }, + fromAddress: '0x552008c0f6870c2f77e5cC1d2eb9bdff03e30Ea0', + toChainId: 100, + toToken: { + address: '0x0000000000000000000000000000000000000000', + symbol: 'xDai', + decimals: 18, + chainId: 100, + name: 'xDai', + coinKey: CoinKey.DAI, + priceUSD: '1', + logoURI: + 'https://static.debank.com/image/xdai_token/logo_url/xdai/1207e67652b691ef3bfe04f89f4b5362.png', + }, + slippage: 0.03, + }, + estimate: { + fromAmount: '1000000000000000000', + toAmount: '1029578874934906550', + toAmountMin: '1029578874934906550', + approvalAddress: '0x5A9Fd7c39a6C488E715437D7b1f3C823d5596eD1', + gasCosts: [ + { + type: 'SEND', + price: '195.1924', + estimate: '417000', + limit: '521250', + amount: '81395231', + amountUSD: '0.09', + token: { + address: '0x0000000000000000000000000000000000000000', + symbol: 'FTM', + decimals: 18, + chainId: 250, + name: 'FTM', + coinKey: CoinKey.FTM, + priceUSD: '1.0829', + logoURI: + 'https://static.debank.com/image/ftm_token/logo_url/ftm/33fdb9c5067e94f3a1b9e78f6fa86984.png', + }, + }, + ], + executionDuration: 673.77246, + }, + includedSteps: [ + { + id: 'b3533c0a-c520-411c-996c-81e5979087e7', + type: 'swap', + tool: '0x', + action: { + fromChainId: 250, + toChainId: 250, + fromToken: { + address: '0x0000000000000000000000000000000000000000', + symbol: 'FTM', + decimals: 18, + chainId: 250, + name: 'FTM', + coinKey: CoinKey.FTM, + priceUSD: '1.0829', + logoURI: + 'https://static.debank.com/image/ftm_token/logo_url/ftm/33fdb9c5067e94f3a1b9e78f6fa86984.png', + }, + toToken: { + address: '0x8d11ec38a3eb5e956b052f67da8bdc9bef8abf3e', + decimals: 18, + symbol: 'DAI', + chainId: 250, + coinKey: CoinKey.DAI, + name: 'DAI', + logoURI: + 'https://static.debank.com/image/ftm_token/logo_url/0x8d11ec38a3eb5e956b052f67da8bdc9bef8abf3e/549c4205dbb199f1b8b03af783f35e71.png', + priceUSD: '1', + }, + fromAmount: '1000000000000000000', + slippage: 0.03, + fromAddress: '0x5A9Fd7c39a6C488E715437D7b1f3C823d5596eD1', + toAddress: '0x5A9Fd7c39a6C488E715437D7b1f3C823d5596eD1', + }, + estimate: { + fromAmount: '1000000000000000000', + toAmount: '1078489833234765941', + toAmountMin: '1078489833234765941', + approvalAddress: '0xdef189deaef76e379df891899eb5a00a94cbc250', + executionDuration: 30, + feeCosts: [], + gasCosts: [ + { + type: 'SEND', + price: '195.1924', + estimate: '277000', + limit: '346250', + amount: '54068295', + amountUSD: '0.06', + token: { + address: '0x0000000000000000000000000000000000000000', + symbol: 'FTM', + decimals: 18, + chainId: 250, + name: 'FTM', + coinKey: CoinKey.FTM, + priceUSD: '1.0829', + logoURI: + 'https://static.debank.com/image/ftm_token/logo_url/ftm/33fdb9c5067e94f3a1b9e78f6fa86984.png', + }, + }, + ], + data: { + chainId: 250, + price: '1.078489833234765941', + guaranteedPrice: '1.067704934902418281', + estimatedPriceImpact: '0', + to: '0xdef189deaef76e379df891899eb5a00a94cbc250', + data: '0x415565b0000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee0000000000000000000000008d11ec38a3eb5e956b052f67da8bdc9bef8abf3e0000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000000ed13ffb39ca4b6900000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000460000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000040000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee0000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000021be370d5312f44cb42ce377bc9b8a0cef1a4c830000000000000000000000008d11ec38a3eb5e956b052f67da8bdc9bef8abf3e000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000253706f6f6b79537761700000000000000000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000000ed13ffb39ca4b69000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000f491e7b69e4244ad4002bc14e878a34207e38c290000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000200000000000000000000000021be370d5312f44cb42ce377bc9b8a0cef1a4c830000000000000000000000008d11ec38a3eb5e956b052f67da8bdc9bef8abf3e000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000200000000000000000000000021be370d5312f44cb42ce377bc9b8a0cef1a4c83000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee0000000000000000000000000000000000000000000000000000000000000000869584cd0000000000000000000000001000000000000000000000000000000000000011000000000000000000000000000000000000000000000069c45436f16230ac5e', + value: '1000000000000000000', + gas: '277000', + estimatedGas: '277000', + from: '0x552008c0f6870c2f77e5cc1d2eb9bdff03e30ea0', + gasPrice: '196000000000', + protocolFee: '0', + minimumProtocolFee: '0', + buyTokenAddress: '0x8d11ec38a3eb5e956b052f67da8bdc9bef8abf3e', + sellTokenAddress: + '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee', + buyAmount: '1078489833234765941', + sellAmount: '1000000000000000000', + sources: [ + { + name: 'MultiHop', + proportion: '0', + }, + { + name: 'Beethovenx', + proportion: '0', + }, + { + name: 'Curve', + proportion: '0', + }, + { + name: 'Curve_V2', + proportion: '0', + }, + { + name: 'Geist', + proportion: '0', + }, + { + name: 'JetSwap', + proportion: '0', + }, + { + name: 'MorpheusSwap', + proportion: '0', + }, + { + name: 'SpiritSwap', + proportion: '0', + }, + { + name: 'SpookySwap', + proportion: '1', + }, + { + name: 'SushiSwap', + proportion: '0', + }, + { + name: 'Synapse', + proportion: '0', + }, + ], + orders: [ + { + makerToken: '0x8d11ec38a3eb5e956b052f67da8bdc9bef8abf3e', + takerToken: '0x21be370d5312f44cb42ce377bc9b8a0cef1a4c83', + makerAmount: '1078489833234765941', + takerAmount: '1000000000000000000', + fillData: { + tokenAddressPath: [ + '0x21be370d5312f44cb42ce377bc9b8a0cef1a4c83', + '0x8d11ec38a3eb5e956b052f67da8bdc9bef8abf3e', + ], + router: '0xf491e7b69e4244ad4002bc14e878a34207e38c29', + }, + source: 'SpookySwap', + sourcePathId: + '0xf253d45f0a4ce92e24547b1f08580fd905361dcf561bec1ab399ce466be98ebe', + type: 0, + }, + ], + allowanceTarget: '0x0000000000000000000000000000000000000000', + sellTokenToEthRate: '1', + buyTokenToEthRate: '1.077193214043137423', + }, + }, + }, + { + id: '0x1fe63a154d1e1e8c23395d79485d3faa84e7f8697cb36fe06d3d376dab04bc97', + type: 'cross', + tool: 'connext', + action: { + fromChainId: 250, + toChainId: 100, + fromToken: { + address: '0x8d11ec38a3eb5e956b052f67da8bdc9bef8abf3e', + decimals: 18, + symbol: 'DAI', + chainId: 250, + coinKey: CoinKey.DAI, + name: 'DAI', + logoURI: + 'https://static.debank.com/image/ftm_token/logo_url/0x8d11ec38a3eb5e956b052f67da8bdc9bef8abf3e/549c4205dbb199f1b8b03af783f35e71.png', + priceUSD: '1', + }, + toToken: { + address: '0x0000000000000000000000000000000000000000', + symbol: 'xDai', + decimals: 18, + chainId: 100, + name: 'xDai', + coinKey: CoinKey.DAI, + priceUSD: '1', + logoURI: + 'https://static.debank.com/image/xdai_token/logo_url/xdai/1207e67652b691ef3bfe04f89f4b5362.png', + }, + fromAmount: '1078489833234765941', + fromAddress: '0x5A9Fd7c39a6C488E715437D7b1f3C823d5596eD1', + slippage: 0.03, + toAddress: '0x5A9Fd7c39a6C488E715437D7b1f3C823d5596eD1', + }, + estimate: { + fromAmount: '1078489833234765941', + toAmount: '1029578874934906550', + toAmountMin: '1029578874934906550', + approvalAddress: '0x0D29d9Fa94a23e0D2F06EfC79c25144A8F51Fc4b', + executionDuration: 643.77246, + feeCosts: [ + { + name: 'Gas Fee', + description: + 'Covers gas expense for sending funds to user on receiving chain.', + percentage: '0.04451659339198891462', + token: { + address: '0x8d11ec38a3eb5e956b052f67da8bdc9bef8abf3e', + decimals: 18, + symbol: 'DAI', + chainId: 250, + coinKey: CoinKey.DAI, + name: 'DAI', + logoURI: + 'https://static.debank.com/image/ftm_token/logo_url/0x8d11ec38a3eb5e956b052f67da8bdc9bef8abf3e/549c4205dbb199f1b8b03af783f35e71.png', + priceUSD: '1', + }, + amount: '48010693383506008', + amountUSD: '48010693383506008.00', + }, + { + name: 'Relay Fee', + description: + 'Covers gas expense for claiming user funds on receiving chain.', + percentage: '0.00033474585351739062', + token: { + address: '0x8d11ec38a3eb5e956b052f67da8bdc9bef8abf3e', + decimals: 18, + symbol: 'DAI', + chainId: 250, + coinKey: CoinKey.DAI, + name: 'DAI', + logoURI: + 'https://static.debank.com/image/ftm_token/logo_url/0x8d11ec38a3eb5e956b052f67da8bdc9bef8abf3e/549c4205dbb199f1b8b03af783f35e71.png', + priceUSD: '1', + }, + amount: '361019999736000', + amountUSD: '361019999736000.00', + }, + { + name: 'Router Fee', + description: 'Router service fee.', + percentage: '0.00050000000000000003', + token: { + address: '0x8d11ec38a3eb5e956b052f67da8bdc9bef8abf3e', + decimals: 18, + symbol: 'DAI', + chainId: 250, + coinKey: CoinKey.DAI, + name: 'DAI', + logoURI: + 'https://static.debank.com/image/ftm_token/logo_url/0x8d11ec38a3eb5e956b052f67da8bdc9bef8abf3e/549c4205dbb199f1b8b03af783f35e71.png', + priceUSD: '1', + }, + amount: '539244916617383', + amountUSD: '539244916617383.00', + }, + ], + gasCosts: [ + { + type: 'SEND', + price: '195.1924', + estimate: '140000', + limit: '175000', + amount: '27326936', + amountUSD: '0.03', + token: { + address: '0x0000000000000000000000000000000000000000', + symbol: 'FTM', + decimals: 18, + chainId: 250, + name: 'FTM', + coinKey: CoinKey.FTM, + priceUSD: '1.0829', + logoURI: + 'https://static.debank.com/image/ftm_token/logo_url/ftm/33fdb9c5067e94f3a1b9e78f6fa86984.png', + }, + }, + ], + data: { + bid: { + user: '0x552008c0f6870c2f77e5cC1d2eb9bdff03e30Ea0', + router: '0x826Ccd5eD8ca665555Fe45A4f045b61516b241C0', + initiator: '0x552008c0f6870c2f77e5cC1d2eb9bdff03e30Ea0', + sendingChainId: 250, + sendingAssetId: + '0x8d11ec38a3eb5e956b052f67da8bdc9bef8abf3e', + amount: '1078489833234765941', + receivingChainId: 100, + receivingAssetId: + '0x0000000000000000000000000000000000000000', + amountReceived: '1029939894934642550', + receivingAddress: + '0x997f29174a766A1DA04cf77d135d59Dd12FB54d1', + transactionId: + '0x1fe63a154d1e1e8c23395d79485d3faa84e7f8697cb36fe06d3d376dab04bc97', + expiry: 1647616226, + callDataHash: + '0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470', + callTo: '0x0000000000000000000000000000000000000000', + encryptedCallData: '0x', + sendingChainTxManagerAddress: + '0x0D29d9Fa94a23e0D2F06EfC79c25144A8F51Fc4b', + receivingChainTxManagerAddress: + '0x115909BDcbaB21954bEb4ab65FC2aBEE9866fa93', + bidExpiry: 1647357329, + }, + bidSignature: + '0x877535545418be167ada99877ff6ef3bba0d4b28cbe6b05dddd6063744ef6f117edd31b28036a4ea69c810392a81b4d467f4f4f2e03388ea7df4329542d49ad91c', + gasFeeInReceivingToken: '48010693383506008', + totalFee: '48910958299859391', + metaTxRelayerFee: '361019999736000', + routerFee: '539244916617383', + serverSign: true, + }, + }, + }, + ], + }, + ], + }, + ], +}; diff --git a/packages/widget/src/utils/elements.ts b/packages/widget/src/utils/elements.ts index a4c7c674b..8a214a2b6 100644 --- a/packages/widget/src/utils/elements.ts +++ b/packages/widget/src/utils/elements.ts @@ -1,3 +1,4 @@ export enum ElementId { SwapContent = 'swap-content', + TransactionContent = 'transaction-content', } diff --git a/packages/widget/src/utils/routes.ts b/packages/widget/src/utils/routes.ts index f6b3de094..7454d3212 100644 --- a/packages/widget/src/utils/routes.ts +++ b/packages/widget/src/utils/routes.ts @@ -4,6 +4,7 @@ export const routes = { fromToken: '/select-from-token', toToken: '/select-to-token', selectWallet: '/select-wallet', + transaction: '/transaction', }; export type RouteType = keyof typeof routes;