From 158edf2266377f77bee2025daa7f42df51965858 Mon Sep 17 00:00:00 2001 From: hotequil Date: Wed, 13 Nov 2024 17:05:09 -0300 Subject: [PATCH] CU-86a5j1veu-NEON3 - Swap - Implement Swap Details Page --- package-lock.json | 112 +++------ package.json | 12 +- .../src/assets/images/simple-swap-logo.png | Bin 2315 -> 0 bytes src/renderer/src/components/Details.tsx | 90 ++++++++ .../GreyTokenSelect/GreyTokenSelectItem.tsx | 5 + .../src/components/GreyTokenSelect/index.tsx | 8 +- .../src/components/Modal/SideModal.tsx | 5 +- src/renderer/src/components/Stepper.tsx | 44 +++- src/renderer/src/constants/swap.ts | 2 + src/renderer/src/locales/en/modals.json | 29 ++- src/renderer/src/locales/en/pages.json | 1 - .../SwapDetailsModalTokenDetails.tsx | 25 ++ .../src/routes/modals/SwapDetails/index.tsx | 216 ++++++++++++++++++ src/renderer/src/routes/modalsRouter.tsx | 16 +- .../pages/Swap/SwapErrorModalContent.tsx | 22 -- .../src/routes/pages/Swap/SwapPageContent.tsx | 65 ++---- .../pages/Swap/SwapSuccessModalContent.tsx | 155 ------------- .../src/store/reducers/AuthReducer.ts | 17 +- src/shared/@types/i18next-resources.d.ts | 24 +- src/shared/@types/modal.ts | 2 +- src/shared/@types/store.ts | 10 +- 21 files changed, 524 insertions(+), 336 deletions(-) delete mode 100644 src/renderer/src/assets/images/simple-swap-logo.png create mode 100644 src/renderer/src/components/Details.tsx create mode 100644 src/renderer/src/routes/modals/SwapDetails/SwapDetailsModalTokenDetails.tsx create mode 100644 src/renderer/src/routes/modals/SwapDetails/index.tsx delete mode 100644 src/renderer/src/routes/pages/Swap/SwapErrorModalContent.tsx delete mode 100644 src/renderer/src/routes/pages/Swap/SwapSuccessModalContent.tsx diff --git a/package-lock.json b/package-lock.json index 4d0e4e3ff..98f05b2bc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,13 +10,13 @@ "hasInstallScript": true, "license": "MIT", "dependencies": { - "@cityofzion/blockchain-service": "1.8.0", + "@cityofzion/blockchain-service": "1.10.0", "@cityofzion/bs-asteroid-sdk": "0.9.0", - "@cityofzion/bs-electron": "0.1.19", - "@cityofzion/bs-ethereum": "2.7.0", - "@cityofzion/bs-neo-legacy": "1.6.0", - "@cityofzion/bs-neo3": "1.8.2", - "@cityofzion/bs-swap": "0.1.1", + "@cityofzion/bs-electron": "0.1.21", + "@cityofzion/bs-ethereum": "2.7.2", + "@cityofzion/bs-neo-legacy": "1.6.2", + "@cityofzion/bs-neo3": "1.8.3", + "@cityofzion/bs-swap": "0.2.1", "@cityofzion/neon-core": "5.5.1", "@cityofzion/neon-js": "5.5.1", "@cityofzion/wallet-connect-sdk-wallet-core": "4.4.0", @@ -568,9 +568,9 @@ } }, "node_modules/@cityofzion/blockchain-service": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/@cityofzion/blockchain-service/-/blockchain-service-1.8.0.tgz", - "integrity": "sha512-g4FeVLGMxKirbI16q6KpAQ3gsZJG6uzGEOkTEU7Xqahic+wDtp9EOYMt47327g8WiNFr9uw6L6BRLgTFglz0TQ==", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@cityofzion/blockchain-service/-/blockchain-service-1.10.0.tgz", + "integrity": "sha512-VaHlwHFSawK3TilN0wgv8tEOvBLuaKxFl7fNIGacnnpj4GwWyc+0xzv0ZwwzwgDgwneyM153roKVkcuzH/k+fg==", "license": "MIT", "dependencies": { "@ledgerhq/hw-transport": "~6.30.5", @@ -604,12 +604,12 @@ } }, "node_modules/@cityofzion/bs-electron": { - "version": "0.1.19", - "resolved": "https://registry.npmjs.org/@cityofzion/bs-electron/-/bs-electron-0.1.19.tgz", - "integrity": "sha512-+jNjCiSCgUstShrwyan8nqaipeZDtKMEn3Qz6Eq7a3Ebxgq2bsyMGqcG+ntvrsjU0Voa/AonaLCNrdL9f9lyWw==", + "version": "0.1.21", + "resolved": "https://registry.npmjs.org/@cityofzion/bs-electron/-/bs-electron-0.1.21.tgz", + "integrity": "sha512-Um+zCAvxPcZrQ8bm41YaWBX8K32wc9TBHDChOIZLlOfGj5yV+d7QB2v99iST47TkmjGLGTSTFLFQUewYdNQZlg==", "license": "MIT", "dependencies": { - "@cityofzion/blockchain-service": "1.8.0", + "@cityofzion/blockchain-service": "1.10.0", "lodash.clonedeep": "~4.5.0" }, "peerDependencies": { @@ -618,12 +618,12 @@ } }, "node_modules/@cityofzion/bs-ethereum": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/@cityofzion/bs-ethereum/-/bs-ethereum-2.7.0.tgz", - "integrity": "sha512-tl63b6IvlsBLtd/1KTmoP+XjFLbWWfy9rzeDRYcq+jAoOvjIPEZ1LyAAr8AD2pMax24ZED5YXhTBGEM7UXSdVg==", + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/@cityofzion/bs-ethereum/-/bs-ethereum-2.7.2.tgz", + "integrity": "sha512-5kQJ4GWaPZ57FW72Zw5/l5LtqKxUjddANvydNfl65HyZtdHrT0hM5s5XAbCwDBjvjT5XCt+47tQzlhuTShF4EQ==", "license": "MIT", "dependencies": { - "@cityofzion/blockchain-service": "1.8.0", + "@cityofzion/blockchain-service": "1.10.0", "@ethersproject/abstract-signer": "~5.7.0", "@ethersproject/bignumber": "5.7.0", "@ethersproject/bytes": "5.7.0", @@ -757,12 +757,12 @@ } }, "node_modules/@cityofzion/bs-neo-legacy": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@cityofzion/bs-neo-legacy/-/bs-neo-legacy-1.6.0.tgz", - "integrity": "sha512-oJs9c6BUekhtTDxLcUo/4f3oCvRA8L5snxKfL0fq9dJDjvm731rdSPI6abq0d2FCfsuve/s47D25SLwcppUDvg==", + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/@cityofzion/bs-neo-legacy/-/bs-neo-legacy-1.6.2.tgz", + "integrity": "sha512-GnwxdSqvJ5NoyPbL9QdVx1kUqQpivSByOjoRIEeMxR60hJ07f78mOThbLey80fQyfR3TZiMzpk8BQr4YRIFZ1Q==", "license": "MIT", "dependencies": { - "@cityofzion/blockchain-service": "1.8.0", + "@cityofzion/blockchain-service": "1.10.0", "@cityofzion/bs-asteroid-sdk": "0.9.0", "@cityofzion/dora-ts": "0.0.11", "@cityofzion/neon-js": "4.8.3" @@ -850,11 +850,12 @@ } }, "node_modules/@cityofzion/bs-neo3": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/@cityofzion/bs-neo3/-/bs-neo3-1.8.2.tgz", - "integrity": "sha512-Q5I7ogjoo6YEyniC43EWaOCT91gHX0vZx4cTQ+UnDBvOr5oiZThBSK7nkFT428CW6hZR20YCuMQdWvFkfnpvoA==", + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@cityofzion/bs-neo3/-/bs-neo3-1.8.3.tgz", + "integrity": "sha512-8fHDxIv4wTdB7m7HKqu5xVb4Rw8rxV+5AYMcS6SsMyZTdMQGnqxW2QfvZ17wLuCdbScu4HJIIPKurDUujkl5xQ==", + "license": "MIT", "dependencies": { - "@cityofzion/blockchain-service": "1.9.0", + "@cityofzion/blockchain-service": "1.10.0", "@cityofzion/bs-asteroid-sdk": "0.9.0", "@cityofzion/dora-ts": "0.0.11", "@cityofzion/neon-core": "5.5.1", @@ -868,17 +869,10 @@ "query-string": "7.1.3" } }, - "node_modules/@cityofzion/bs-neo3/node_modules/@cityofzion/blockchain-service": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@cityofzion/blockchain-service/-/blockchain-service-1.9.0.tgz", - "integrity": "sha512-lolAD/TzXyIZxifYI/mFBvZSeBIblWfotfdpKjpfarVCZFQmNnOY/ebeX+5o+Twq+W1H+YebjxtYMt+zlvCUiw==", - "dependencies": { - "@ledgerhq/hw-transport": "~6.30.5", - "axios": "1.5.1" - } - }, "node_modules/@cityofzion/bs-neo3/node_modules/@ledgerhq/hw-transport": { "version": "6.30.6", + "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport/-/hw-transport-6.30.6.tgz", + "integrity": "sha512-fT0Z4IywiuJuZrZE/+W0blkV5UCotDPFTYKLkKCLzYzuE6javva7D/ajRaIeR+hZ4kTmKF4EqnsmDCXwElez+w==", "license": "Apache-2.0", "dependencies": { "@ledgerhq/devices": "^8.3.0", @@ -889,6 +883,8 @@ }, "node_modules/@cityofzion/bs-neo3/node_modules/axios": { "version": "1.5.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.5.1.tgz", + "integrity": "sha512-Q28iYCWzNHjAm+yEAot5QaAMxhMghWLFVf7rRdwhUI+c2jix2DUXjAHXVi+s1ibs3mjPO/cCgbA++3BjD0vP/A==", "license": "MIT", "dependencies": { "follow-redirects": "^1.15.0", @@ -904,47 +900,17 @@ } }, "node_modules/@cityofzion/bs-swap": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@cityofzion/bs-swap/-/bs-swap-0.1.1.tgz", - "integrity": "sha512-kIJcOMQDTicj7FJWL5n6o5E1L12zP/QBouTWu2XNOGjNtWEGIBpckqzYChzsZwrBjpuZD4NhGeNgXaMj3ZVlMg==", + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@cityofzion/bs-swap/-/bs-swap-0.2.1.tgz", + "integrity": "sha512-LB3pHjYHyb8Gruhux8zi5AfKaYrATIDL6bPKu72Z9QS6Zs5NaOnRDN5UzugT6rrutWJloEelI5Vw8zUMZ1s3WA==", "license": "MIT", "dependencies": { - "@cityofzion/blockchain-service": "1.8.0", - "@cityofzion/bs-neo3": "1.8.0", + "@cityofzion/blockchain-service": "1.10.0", + "@cityofzion/bs-neo3": "1.8.3", "axios": "1.5.1", "lodash": "~4.17.21" } }, - "node_modules/@cityofzion/bs-swap/node_modules/@cityofzion/bs-neo3": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/@cityofzion/bs-neo3/-/bs-neo3-1.8.0.tgz", - "integrity": "sha512-YW++gN2qvl6ZhWf82JFkCHazNsVLJmskS3rIP38rFjgZqVNDrVI7jCMvMeT9k+Qwh9pAKBZHGjAYNrpk8cNqqw==", - "dependencies": { - "@cityofzion/blockchain-service": "1.8.0", - "@cityofzion/bs-asteroid-sdk": "0.9.0", - "@cityofzion/dora-ts": "0.0.11", - "@cityofzion/neon-core": "5.5.1", - "@cityofzion/neon-dappkit": "0.4.1", - "@cityofzion/neon-js": "5.5.1", - "@ledgerhq/hw-transport": "~6.30.5", - "axios": "1.5.1", - "bignumber.js": "^9.1.2", - "isomorphic-ws": "^5.0.0", - "lodash.clonedeep": "^4.5.0", - "query-string": "7.1.3" - } - }, - "node_modules/@cityofzion/bs-swap/node_modules/@ledgerhq/hw-transport": { - "version": "6.30.6", - "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport/-/hw-transport-6.30.6.tgz", - "integrity": "sha512-fT0Z4IywiuJuZrZE/+W0blkV5UCotDPFTYKLkKCLzYzuE6javva7D/ajRaIeR+hZ4kTmKF4EqnsmDCXwElez+w==", - "dependencies": { - "@ledgerhq/devices": "^8.3.0", - "@ledgerhq/errors": "^6.16.4", - "@ledgerhq/logs": "^6.12.0", - "events": "^3.3.0" - } - }, "node_modules/@cityofzion/bs-swap/node_modules/axios": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/axios/-/axios-1.5.1.tgz", @@ -956,14 +922,6 @@ "proxy-from-env": "^1.1.0" } }, - "node_modules/@cityofzion/bs-swap/node_modules/isomorphic-ws": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz", - "integrity": "sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==", - "peerDependencies": { - "ws": "*" - } - }, "node_modules/@cityofzion/dora-ts": { "version": "0.0.11", "dependencies": { diff --git a/package.json b/package.json index ba569f24c..86d27cbe1 100644 --- a/package.json +++ b/package.json @@ -29,13 +29,13 @@ "playwright:report": "npx playwright show-report" }, "dependencies": { - "@cityofzion/blockchain-service": "1.8.0", + "@cityofzion/blockchain-service": "1.10.0", "@cityofzion/bs-asteroid-sdk": "0.9.0", - "@cityofzion/bs-electron": "0.1.19", - "@cityofzion/bs-ethereum": "2.7.0", - "@cityofzion/bs-neo-legacy": "1.6.0", - "@cityofzion/bs-neo3": "1.8.2", - "@cityofzion/bs-swap": "0.1.1", + "@cityofzion/bs-electron": "0.1.21", + "@cityofzion/bs-ethereum": "2.7.2", + "@cityofzion/bs-neo-legacy": "1.6.2", + "@cityofzion/bs-neo3": "1.8.3", + "@cityofzion/bs-swap": "0.2.1", "@cityofzion/neon-core": "5.5.1", "@cityofzion/neon-js": "5.5.1", "@cityofzion/wallet-connect-sdk-wallet-core": "4.4.0", diff --git a/src/renderer/src/assets/images/simple-swap-logo.png b/src/renderer/src/assets/images/simple-swap-logo.png deleted file mode 100644 index 66292840a753dc3b2e3021985a25b6e4fee88ad8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2315 zcmV+m3H0`fP)Ckn$|(BJW@<=6Aj+t$RG6^_tdtnb zQVbbk1_VK&O%0@?lmOiY`4P%LM7g_n?=IYXzvJ`ldGB!da(C~~-kss<_sl%=-S2$o z?>px?@B5zf?TUEt;K73j4<0;}J{;*MR4p)L0&e1G_}M5%s?kzJT-kgo=AYNO%sDC^ zN*4VhnwsyM@s2O?IDQV!@c3mBe`9#5b5J~#Bz#h2)XtAhgCFK2wZC3lr!yqcNk~Iv^eoC5fVmrglO6v&NMN@YA0|cE^d!K=DwLD2ixc zVXjAzyAlynO^!v33CP>xp(GKIKB8{EnQ2U7t>hC_8`&IL>bxi(N)mmtGy`uXL_rrsi}!Ud(whTfJ+1d>I2v3D?$Kv6lWpPmEn4m-a0$2%+zx)L zr68)cm>m49B1mp31oVIy$N_{IdZL+3auJ;S| z{t|s3_OA*2D)@lr84QNNN5MaXH>!nZ-ampLmI9IY?y0p+h8VwGkW1e9+pUS{iwArr z;ikGIH&j^-!Bli>8|fEF{f>}4dsRoKx+YJa%$1p(uP%UA=xnhX6P63>Pxn+GUM_*l&sjBi56BgBFL<@|jAYwCL3ysM4}t#%hk)C~ii1Mq zB!%Sc_~cpe3X~lqcCskwIcRf8_pTeh&yU3lu^#z9t@So*{>zZoir+sHJE0puTDYaO zF#3L+yu;v?NaJKr6e}27rm5Q0N5qaj#X|8@Fpsd0;8<{$)}Ia@xX#r)jQJRgodpMa*Xu4(}{;8urM$AOgxq*7`UWhS>_XCN1m27UBc)Q7}yoKTqf46a}vG@ zK8-=1Exlu{mS>smnzkGFr$A1^I!#Nrp!eYU|FkS8>KU;sbyQlu5#WVlMM_t|e4E8u z846&G*1>p&@z}4m+&qv$@g%)}RIK%9eH7^da5XrV?nbQj`VZ=%xF%|u<+y)~?*TrH z`%H5~>$gJlQ24*p^hr_x@)phUpE?l?&CZ^lCpu5L(S0pG1To!QQf2i(6AV^l7K|~+ z+<=)YS%86~Yv@q3&YjYHu@m)$EJfYaF7}d^egsjGb|2Dfx<%|rxjvS{Ux{^1dvxc= z{+~eq`K}Za-B&GmvzA}2*9PSlvErj;`=pk6B&`p1$xbj1lFY{_>F-gNR!3eaX!m3s zKb4x%MI~Tm(qov4t{A2)b6ZA^#eM#1t?Ng=B)zq11IoXHhc))#r2khR$E1J2?eQ=M zzq&(X@XGk6IW-gdats%`7amrw!~I>jt`h4G=%)S;4iM{po=065JN)`4(xO$wwVqwL zoD}PNE)wfTwuu$>En;2IRxR_CUKgUi0V)_;-t#iNN435SgKIuttm%K10#J}>!b_Z8 z*h4T#J8QB6HC28m5bP2ZT~bv|oxzqmW5A6}$74=#dSv79te+Gxplpi)E(dNsUj8|; ztB!5mC;bCjhTUQ(_aU(>^fvS*oFVTleZGTdNMd8Bn^+e4qaa +const Root = ({ className, children, ...props }: TRootProps) => { + return ( +
+ {children} +
+ ) +} + +type THeaderProps = { + label: string + icon?: JSX.Element +} & ComponentProps<'div'> +const Header = ({ label, icon, children, ...props }: THeaderProps) => { + return ( +
+
+ {icon && cloneElement(icon, { className: StyleHelper.mergeStyles('text-blue w-6 h-6', icon.props.className) })} + + {label} + + {children} +
+ + +
+ ) +} +type TBodyProps = ComponentProps<'div'> +const Body = ({ className, children, ...props }: TBodyProps) => { + return ( +
+ {children} +
+ ) +} + +type TPanelProps = { label: string } & ComponentProps<'div'> +const Panel = ({ className, children, label, ...props }: TPanelProps) => { + return ( +
+
{label}
+ + {children} +
+ ) +} + +type TItemProps = { label: string; copyable?: boolean } & ComponentProps<'div'> +const Item = ({ label, children, copyable, className, ...props }: TItemProps) => { + const handleCopy = () => { + if (typeof children !== 'string') return + UtilsHelper.copyToClipboard(children) + } + return ( +
+
+ {label} + +
+ {typeof children === 'string' ? {children} : children} + + {copyable && ( + } + size="sm" + onClick={handleCopy} + compacted + /> + )} +
+
+ + +
+ ) +} + +export const Details = { Root, Header, Body, Panel, Item } diff --git a/src/renderer/src/components/GreyTokenSelect/GreyTokenSelectItem.tsx b/src/renderer/src/components/GreyTokenSelect/GreyTokenSelectItem.tsx index d7947d5e9..1df72ce38 100644 --- a/src/renderer/src/components/GreyTokenSelect/GreyTokenSelectItem.tsx +++ b/src/renderer/src/components/GreyTokenSelect/GreyTokenSelectItem.tsx @@ -1,5 +1,6 @@ import { Fragment, useEffect, useState } from 'react' import defaultTokenLogo from '@renderer/assets/images/default-token-logo.png' +import { NumberHelper } from '@renderer/helpers/NumberHelper' import { TGreyTokenSelectToken } from '.' @@ -30,6 +31,10 @@ export const GreyTokenSelectItem = ({ token }: TProps) => { {token.symbol} {token.network && {` | ${token.network}`}} + + {token.amount && ( + {NumberHelper.formatString(token.amount, 6)} + )} ) } diff --git a/src/renderer/src/components/GreyTokenSelect/index.tsx b/src/renderer/src/components/GreyTokenSelect/index.tsx index 275ca8e0d..79a758951 100644 --- a/src/renderer/src/components/GreyTokenSelect/index.tsx +++ b/src/renderer/src/components/GreyTokenSelect/index.tsx @@ -61,7 +61,9 @@ export const GreyTokenSelect = ({ if (balance) { filtered = filtered.map(token => { const tokenHash = UtilsHelper.normalizeHash(token.hash!) - const tokenBalance = balance.tokensBalances.find(tokenBalance => tokenBalance.token.hash === tokenHash) + const tokenBalance = balance.tokensBalances.find( + tokenBalance => UtilsHelper.normalizeHash(tokenBalance.token.hash) === tokenHash + ) return { ...token, @@ -144,7 +146,7 @@ export const GreyTokenSelect = ({ position: 'relative', }} > - {rowVirtualizer.getVirtualItems().map(virtualItem => { + {rowVirtualizer.getVirtualItems().map((virtualItem, _, array) => { const row = filteredTokensByText[virtualItem.index] return ( @@ -162,7 +164,7 @@ export const GreyTokenSelect = ({ - + {virtualItem.index + 1 !== array.length && } ) })} diff --git a/src/renderer/src/components/Modal/SideModal.tsx b/src/renderer/src/components/Modal/SideModal.tsx index 40aca88ac..0408266f0 100644 --- a/src/renderer/src/components/Modal/SideModal.tsx +++ b/src/renderer/src/components/Modal/SideModal.tsx @@ -10,8 +10,9 @@ import { ModalContainer } from './ModalContainer' const widthBySizes: Partial> = { md: '25.875rem', sm: '20.625rem', - xl: '62.5rem', - lg: '45rem', + lg: '32rem', + xl: '45rem', + '1xl': '62.5rem', } export const SideModal = () => { diff --git a/src/renderer/src/components/Stepper.tsx b/src/renderer/src/components/Stepper.tsx index 802ca47f5..b6fb362e1 100644 --- a/src/renderer/src/components/Stepper.tsx +++ b/src/renderer/src/components/Stepper.tsx @@ -1,16 +1,35 @@ import { Fragment } from 'react' import { StyleHelper } from '@renderer/helpers/StyleHelper' +export type TStepperCurrentState = 'success' | 'error' + type TProps = { steps: string[] currentStep?: number + currentState?: TStepperCurrentState + theme?: 'neon' | 'default' } & React.ComponentProps<'div'> -export const Stepper = ({ steps, currentStep = 1, className, ...props }: TProps) => { +export const Stepper = ({ + steps, + currentStep = 1, + className, + theme = 'default', + currentState = 'success', + ...props +}: TProps) => { return (
{steps.map((step, index) => { const fixedIndex = index + 1 + const isCurrentStep = fixedIndex === currentStep + const isCurrentOrFutureStep = fixedIndex >= currentStep + const isPastStep = fixedIndex < currentStep + const isFutureStep = fixedIndex > currentStep + const isNeonTheme = theme === 'neon' + const isDefaultTheme = theme === 'default' + const isSuccessState = currentState === 'success' + const isErrorState = currentState === 'error' return ( @@ -19,9 +38,12 @@ export const Stepper = ({ steps, currentStep = 1, className, ...props }: TProps) className={StyleHelper.mergeStyles( 'w-6 h-6 rounded-full flex items-center justify-center text-sm font-bold transition-colors', { - 'bg-blue text-asphalt': fixedIndex < currentStep, - 'bg-white text-asphalt': fixedIndex === currentStep, - 'bg-gray-900 text-gray-300': fixedIndex > currentStep, + 'bg-blue text-asphalt': isPastStep && isDefaultTheme, + 'bg-gray-900 text-gray-300': isFutureStep && isDefaultTheme, + 'bg-neon text-asphalt': isPastStep && isNeonTheme, + 'bg-gray-300 text-asphalt': isFutureStep && isNeonTheme, + 'bg-white text-asphalt': isCurrentStep && isSuccessState, + 'bg-pink text-asphalt': isCurrentStep && isErrorState, } )} > @@ -32,9 +54,11 @@ export const Stepper = ({ steps, currentStep = 1, className, ...props }: TProps) className={StyleHelper.mergeStyles( 'text-center w-20 top-8 left-1/2 -translate-x-1/2 text-xs transition-colors absolute', { - 'text-blue': fixedIndex < currentStep, - 'text-white': fixedIndex === currentStep, - 'text-gray-300': fixedIndex > currentStep, + 'text-blue': isPastStep && isDefaultTheme, + 'text-neon': isPastStep && isNeonTheme, + 'text-white': isCurrentStep && isSuccessState, + 'text-pink': isCurrentStep && isErrorState, + 'text-gray-300': isFutureStep, } )} > @@ -45,8 +69,10 @@ export const Stepper = ({ steps, currentStep = 1, className, ...props }: TProps) {fixedIndex < steps.length && (
= currentStep, + 'border-blue': isPastStep && isDefaultTheme, + 'border-gray-900': isCurrentOrFutureStep && isDefaultTheme, + 'border-neon': isPastStep && isNeonTheme, + 'border-gray-300': isCurrentOrFutureStep && isNeonTheme, })} /> )} diff --git a/src/renderer/src/constants/swap.ts b/src/renderer/src/constants/swap.ts index 584a53b01..a017f2277 100644 --- a/src/renderer/src/constants/swap.ts +++ b/src/renderer/src/constants/swap.ts @@ -16,3 +16,5 @@ export const SWAP_NETWORK_BY_BLOCKCHAIN_AND_NETWORK_ID: { '47763': [''], }, } + +export const SWAP_DISCORD_LINK = 'https://discord.gg/zW26BZC5ku' diff --git a/src/renderer/src/locales/en/modals.json b/src/renderer/src/locales/en/modals.json index d8afdcf44..ad2ecd86f 100644 --- a/src/renderer/src/locales/en/modals.json +++ b/src/renderer/src/locales/en/modals.json @@ -525,5 +525,32 @@ "notConnectedMessage": "No hardware wallet found! Please check your connection and search again", "connectedMessage": "Detected your hardware wallet! Opening your wallet...", "searchAgainButtonLabel": "Search again" + }, + "swapDetails": { + "title": "Your swap", + "swapErrorMessage": " Oops! We’ve encountered an error - swap failed", + "transferErrorMessage": " Oops! We’ve encountered an error - transfer failed", + "subtitle": "Your swap details", + "refundedSubtitle": "You’ve been refunded", + "detailsHeaderLabel": "Details", + "detailsHeaderDescription": " We aim to complete swaps in under 7 minutes", + "statusPanelLabel": "Status", + "statusPanelSteps": [ + "Confirm", + "Exchange", + "Complete" + ], + "routingPanelLabel": "Routing", + "routingPanelTransactionFromLabel": "Transaction from", + "routingPanelTransactionToLabel": "Transaction to", + "routingPanelTransactionToLabelPending": "Pending...", + "routingPanelTransactionFeeLabel": "Transaction fee", + "sentPanelLabel": "You sent", + "sentPanelTokenLabel": "Token", + "sentPanelAddressLabel": "Sending address", + "receivePanelLabel": "You’ll receive", + "receivePanelTokenLabel": "Token", + "receivePanelAddressLabel": "Receiving address", + "helpButtonLabel": "Need help? Chat with us" } -} +} \ No newline at end of file diff --git a/src/renderer/src/locales/en/pages.json b/src/renderer/src/locales/en/pages.json index 224bf9abe..113160fc9 100644 --- a/src/renderer/src/locales/en/pages.json +++ b/src/renderer/src/locales/en/pages.json @@ -397,7 +397,6 @@ }, "form": { "title": "What tokens do you want to swap?", - "simpleSwapImgAlt": "Simple swap", "swapFromTitle": "Swap this...", "swapToTitle": "For this...", "balanceLabel": "Balance", diff --git a/src/renderer/src/routes/modals/SwapDetails/SwapDetailsModalTokenDetails.tsx b/src/renderer/src/routes/modals/SwapDetails/SwapDetailsModalTokenDetails.tsx new file mode 100644 index 000000000..495448bb6 --- /dev/null +++ b/src/renderer/src/routes/modals/SwapDetails/SwapDetailsModalTokenDetails.tsx @@ -0,0 +1,25 @@ +import { useTranslation } from 'react-i18next' +import { BlockchainIcon } from '@renderer/components/BlockchainIcon' +import { TBlockchainServiceKey } from '@shared/@types/blockchain' + +type TProps = { + blockchain?: TBlockchainServiceKey + symbol: string + amount: string +} + +export const SwapDetailsModalTokenDetails = ({ amount, blockchain, symbol }: TProps) => { + const { t: commonT } = useTranslation('common') + + return ( +
+ {blockchain && } + + {symbol} + {blockchain && | {commonT(`blockchain.${blockchain}`)}} + + + {amount} +
+ ) +} diff --git a/src/renderer/src/routes/modals/SwapDetails/index.tsx b/src/renderer/src/routes/modals/SwapDetails/index.tsx new file mode 100644 index 000000000..11ad2cfc7 --- /dev/null +++ b/src/renderer/src/routes/modals/SwapDetails/index.tsx @@ -0,0 +1,216 @@ +import { Fragment, useEffect, useRef, useState } from 'react' +import { useTranslation } from 'react-i18next' +import { MdLaunch, MdRefresh } from 'react-icons/md' +import { TbCircleX, TbDiscountCheck, TbReceipt, TbReplace } from 'react-icons/tb' +import { SimpleSwapServiceHelper } from '@cityofzion/bs-swap' +import { BlockchainIcon } from '@renderer/components/BlockchainIcon' +import { Details } from '@renderer/components/Details' +import { Link } from '@renderer/components/Link' +import { Separator } from '@renderer/components/Separator' +import { Stepper, TStepperCurrentState } from '@renderer/components/Stepper' +import { SWAP_DISCORD_LINK } from '@renderer/constants/swap' +import { StringHelper } from '@renderer/helpers/StringHelper' +import { useModalState } from '@renderer/hooks/useModalRouter' +import { useAppDispatch } from '@renderer/hooks/useRedux' +import { SideModalLayout } from '@renderer/layouts/SideModal' +import { bsAggregator } from '@renderer/libs/blockchainService' +import { authReducerActions } from '@renderer/store/reducers/AuthReducer' +import { TSwapRecord } from '@shared/@types/store' +import { match, P } from 'ts-pattern' + +import { SwapDetailsModalTokenDetails } from './SwapDetailsModalTokenDetails' + +type TState = { + swapRecord: TSwapRecord +} + +const swapServiceHelper = new SimpleSwapServiceHelper(import.meta.env.VITE_SIMPLE_SWAP_API_KEY ?? '') + +const stepsByStatus: Record = { + confirming: 2, + exchanging: 3, + finished: 4, + failed: 2, + refunded: 2, +} + +export const SwapDetailsModal = () => { + const modalState = useModalState() + const dispatch = useAppDispatch() + const { t } = useTranslation('modals', { keyPrefix: 'swapDetails' }) + + const [swapRecord, setSwapRecord] = useState(modalState.swapRecord) + + const timeoutRef = useRef() + + const service = bsAggregator.blockchainServicesByName[swapRecord.account.blockchain] + + useEffect(() => { + const getStatus = async () => { + if (!swapRecord.swapId) return + + try { + const response = await swapServiceHelper.getStatus(swapRecord.swapId) + + const updatedSwapRecord: TSwapRecord = { ...swapRecord, swapStatus: response.status, txTo: response.txTo } + setSwapRecord(updatedSwapRecord) + dispatch(authReducerActions.persistSwapRecord(updatedSwapRecord)) + + if (response && response.status === 'finished') { + clearTimeout(timeoutRef.current) + return + } + } catch { + // Empty block + } + + timeoutRef.current = setTimeout(getStatus, 2500) + } + + if ((swapRecord.swapStatus === 'confirming' || swapRecord.swapStatus === 'exchanging') && swapRecord.swapId) + timeoutRef.current = setTimeout(getStatus, 0) + + return () => { + clearTimeout(timeoutRef.current) + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []) + + return ( + } + contentClassName="flex flex-col items-center overflow-auto" + > +
+ {swapRecord.swapStatus === 'failed' || swapRecord.swapStatus === 'refunded' ? ( + + ) : ( + + )} +
+ +
+ {match({ swapStatus: swapRecord.swapStatus, txFrom: swapRecord.txFrom }) + .with({ swapStatus: P.union('refunded', 'failed'), txFrom: P.nullish }, () => ( +

{t('transferErrorMessage')}

+ )) + .with({ swapStatus: P.union('refunded', 'failed'), txFrom: P.string }, () => ( +

{t('swapErrorMessage')}

+ )) + .otherwise(() => ( + + ))} + +

+ {match({ swapStatus: swapRecord.swapStatus }) + .with({ swapStatus: 'refunded' }, () => t('refundedSubtitle')) + .otherwise(() => t('subtitle'))} +

+
+ + + + + }> + {t('detailsHeaderDescription')} + + + + + () + .with({ swapStatus: P.union('failed', 'refunded') }, () => 'error') + .with({ txFrom: P.nullish }, () => 'error') + .otherwise(() => 'success')} + theme="neon" + /> + + + + {swapRecord.txFrom && ( + +
+ + {StringHelper.truncateStringMiddle(swapRecord.txFrom, 20)} +
+
+ )} + + {swapRecord.txFrom && + (swapRecord.txTo || + (swapRecord.swapStatus !== 'refunded' && swapRecord.swapStatus !== 'failed' && !swapRecord.txTo)) && ( + + {match({ txTo: swapRecord.txTo }) + .with({ txTo: P.string }, ({ txTo }) => ( +
+ {swapRecord.tokenTo.blockchain && } + {StringHelper.truncateStringMiddle(txTo, 20)} +
+ )) + .otherwise(() => ( +
+ {t('routingPanelTransactionToLabelPending')} + +
+ ))} +
+ )} + + {swapRecord.fee && ( + + + + )} +
+
+
+ + + + + + + + + {swapRecord.account.address} + + + + + + + + {swapRecord.addressTo} + + + + + } + wide + /> +
+ ) +} diff --git a/src/renderer/src/routes/modalsRouter.tsx b/src/renderer/src/routes/modalsRouter.tsx index 3a59d2ab4..5c90a12e0 100644 --- a/src/renderer/src/routes/modalsRouter.tsx +++ b/src/renderer/src/routes/modalsRouter.tsx @@ -43,6 +43,7 @@ import { DeleteModal } from './modals/PersistContact/DeleteModal' import { SelectAccountModal } from './modals/SelectAccount' import { SelectContact } from './modals/SelectContact' import { SuccessModal } from './modals/Success' +import { SwapDetailsModal } from './modals/SwapDetails' export const modalsRouter: TRoute[] = [ { name: 'import', type: 'side', element: }, @@ -57,10 +58,10 @@ export const modalsRouter: TRoute[] = [ { name: 'export-mnemonic', type: 'side', size: 'md', element: }, { name: 'confirm-password-export', type: 'side', element: }, { name: 'delete-wallet', type: 'side', size: 'md', element: }, - { name: 'create-wallet-step-1', type: 'side', size: 'xl', element: }, - { name: 'create-wallet-step-2', type: 'side', size: 'xl', element: }, - { name: 'create-wallet-step-3', type: 'side', size: 'xl', element: }, - { name: 'create-wallet-step-4', type: 'side', size: 'xl', element: }, + { name: 'create-wallet-step-1', type: 'side', size: '1xl', element: }, + { name: 'create-wallet-step-2', type: 'side', size: '1xl', element: }, + { name: 'create-wallet-step-3', type: 'side', size: '1xl', element: }, + { name: 'create-wallet-step-4', type: 'side', size: '1xl', element: }, { name: 'persist-contact', type: 'side', element: }, { name: 'delete-contact', type: 'side', element: }, { name: 'add-address', type: 'side', element: }, @@ -81,9 +82,9 @@ export const modalsRouter: TRoute[] = [ { name: 'decrypt-key', type: 'side', element: }, { name: 'select-account', type: 'side', element: }, { name: 'network-selection', type: 'side', element: }, - { name: 'migrate-accounts-step-2', type: 'side', size: 'lg', element: }, - { name: 'migrate-accounts-step-3', type: 'side', size: 'lg', element: }, - { name: 'migrate-accounts-step-4', type: 'side', size: 'lg', element: }, + { name: 'migrate-accounts-step-2', type: 'side', size: 'xl', element: }, + { name: 'migrate-accounts-step-3', type: 'side', size: 'xl', element: }, + { name: 'migrate-accounts-step-4', type: 'side', size: 'xl', element: }, { name: 'auto-update-completed', type: 'center', size: 'lg', element: }, { name: 'auto-update-mobile', type: 'center', size: 'lg', element: }, { name: 'auto-update-notes', type: 'center', size: 'lg', element: }, @@ -92,4 +93,5 @@ export const modalsRouter: TRoute[] = [ { name: 'add-network-profile', type: 'side', element: }, { name: 'nft-selection', type: 'side', element: }, { name: 'connect-hardware-wallet', type: 'center', size: 'lg', element: }, + { name: 'swap-details', type: 'side', size: 'lg', element: }, ] diff --git a/src/renderer/src/routes/pages/Swap/SwapErrorModalContent.tsx b/src/renderer/src/routes/pages/Swap/SwapErrorModalContent.tsx deleted file mode 100644 index 320884c11..000000000 --- a/src/renderer/src/routes/pages/Swap/SwapErrorModalContent.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import { useTranslation } from 'react-i18next' - -type TProps = { - error: string -} - -export const SwapErrorModalContent = ({ error }: TProps) => { - const { t } = useTranslation('modals', { keyPrefix: 'dappPermission' }) - - return ( -
-

{t('errorModal.text')}

- -
- {t('errorModal.errorMessageLabel')} -

- {error} -

-
-
- ) -} diff --git a/src/renderer/src/routes/pages/Swap/SwapPageContent.tsx b/src/renderer/src/routes/pages/Swap/SwapPageContent.tsx index 5766514b6..7aa8d6774 100644 --- a/src/renderer/src/routes/pages/Swap/SwapPageContent.tsx +++ b/src/renderer/src/routes/pages/Swap/SwapPageContent.tsx @@ -1,7 +1,7 @@ import { ChangeEvent, Fragment, useEffect, useLayoutEffect, useMemo, useRef } from 'react' import { useTranslation } from 'react-i18next' import { MdArrowForward, MdInfoOutline } from 'react-icons/md' -import { TbArrowDown, TbReplace, TbStepInto, TbStepOut, TbUsers, TbWallet } from 'react-icons/tb' +import { TbArrowDown, TbStepInto, TbStepOut, TbUsers, TbWallet } from 'react-icons/tb' import { VscCircleFilled } from 'react-icons/vsc' import { Account, @@ -13,7 +13,6 @@ import { SwapServiceValidateValue, } from '@cityofzion/blockchain-service' import { SimpleSwapService } from '@cityofzion/bs-swap' -import simpleSwapLogo from '@renderer/assets/images/simple-swap-logo.png' import { ActionStep } from '@renderer/components/ActionStep' import { AlertErrorBanner } from '@renderer/components/AlertErrorBanner' import { Button } from '@renderer/components/Button' @@ -40,9 +39,6 @@ import { authReducerActions } from '@renderer/store/reducers/AuthReducer' import { TBlockchainServiceKey } from '@shared/@types/blockchain' import { IAccountState, TContactAddress, TSwapRecord } from '@shared/@types/store' -import { SwapErrorModalContent } from './SwapErrorModalContent' -import { SwapSuccessModalContent } from './SwapSuccessModalContent' - type TActionsData = { availableTokensToUse: SwapServiceLoadableValue[]> selectedTokenToUse: SwapServiceLoadableValue> @@ -200,46 +196,34 @@ export const SwapPageContent = ({ account }: TProps) => { return } + const swapRecord: TSwapRecord = { + account: actionData.selectedAccountToUse.value, + addressTo: actionData.selectedAddressToReceive.value, + amountTo: actionData.selectedAmountToUse.value, + amountFrom: actionData.selectedAmountToReceive.value, + tokenTo: actionData.selectedTokenToUse.value, + tokenFrom: actionData.selectedTokenToReceive.value, + swapStatus: 'confirming', + swapProvider: 'simpleswap', + fee: actionData.fee, + } + try { const swapResponse = await swapServiceRef.current.swap() - - const swapRecord: TSwapRecord = { - account: actionData.selectedAccountToUse.value, - addressTo: actionData.selectedAddressToReceive.value, - amountTo: actionData.selectedAmountToUse.value, - amountFrom: actionData.selectedAmountToReceive.value, - tokenTo: actionData.selectedTokenToUse.value, - tokenFrom: actionData.selectedTokenToReceive.value, - swapStatus: 'confirming', - swapProvider: 'simpleswap', - swapId: swapResponse.id, - transactionHashes: [swapResponse.transactionHash], - numberOfTransactions: swapResponse.numberOfTransactions, - fee: actionData.fee, - } - - dispatch(authReducerActions.addSwapRecord(swapRecord)) - - modalNavigate('success', { - state: { - heading: t('title'), - headingIcon: , - subtitle: t('form.sendSuccess.subtitle'), - content: , - }, - }) + swapRecord.txFrom = swapResponse.transactionHash + swapRecord.swapId = swapResponse.id } catch (error: any) { console.error(error) - modalNavigate('error', { + swapRecord.swapStatus = 'refunded' + } finally { + dispatch(authReducerActions.persistSwapRecord(swapRecord)) + + modalNavigate('swap-details', { state: { - heading: t('title'), - headingIcon: , - subtitle: t('form.sendError.subtitle'), - description: t('form.sendError.description'), - content: , + swapRecord, }, }) - } finally { + reset() } } @@ -447,11 +431,6 @@ export const SwapPageContent = ({ account }: TProps) => {

{t('explanation.description2')}

- -
- {t('explanation.useTitle')} - {t('form.simpleSwapImgAlt')} -
diff --git a/src/renderer/src/routes/pages/Swap/SwapSuccessModalContent.tsx b/src/renderer/src/routes/pages/Swap/SwapSuccessModalContent.tsx deleted file mode 100644 index 9bf631cab..000000000 --- a/src/renderer/src/routes/pages/Swap/SwapSuccessModalContent.tsx +++ /dev/null @@ -1,155 +0,0 @@ -import { Fragment, ReactNode, useEffect, useRef, useState } from 'react' -import { useTranslation } from 'react-i18next' -import { TbReceipt } from 'react-icons/tb' -import { SwapService, SwapServiceStatusResponse } from '@cityofzion/blockchain-service' -import { Loader } from '@renderer/components/Loader' -import { Separator } from '@renderer/components/Separator' -import { bsAggregator } from '@renderer/libs/blockchainService' -import { TBlockchainServiceKey } from '@shared/@types/blockchain' -import { TSwapRecord } from '@shared/@types/store' - -type TProps = { - swapService: SwapService - swapRecord: TSwapRecord -} - -type TItemProps = { - label: string - value: ReactNode -} -const Item = ({ label, value }: TItemProps) => { - return ( -
- {label} - - {value} -
- ) -} - -export const SwapSuccessModalContent = ({ swapRecord, swapService }: TProps) => { - const { t } = useTranslation('pages', { keyPrefix: 'swap.form.sendSuccess' }) - const [statusResponse, setStatusResponse] = useState({ - status: swapRecord.swapStatus, - transactionHashes: swapRecord.transactionHashes, - }) - - const timeoutRef = useRef() - - useEffect(() => { - const getStatus = async () => { - let response: SwapServiceStatusResponse | undefined - try { - response = await swapService.getStatus() - setStatusResponse(response) - } catch { - // Empty block - } - - if (response && response.status === 'finished') { - clearTimeout(timeoutRef.current) - return - } - - timeoutRef.current = setTimeout(getStatus, 2500) - } - - timeoutRef.current = setTimeout(getStatus, 0) - - return () => { - clearTimeout(timeoutRef.current) - } - }, [swapService]) - - return ( -
-
-
-
- - {t('detailsTitle')} -
- - - -
- - {statusResponse.status} - {statusResponse.status !== 'finished' && statusResponse.status !== 'failed' && ( - - )} -
- } - /> - - - - - - - - - {swapRecord.amountFrom} - {swapRecord.tokenFrom.symbol} -
- } - /> - - - - - {swapRecord.amountTo} - {swapRecord.tokenTo.symbol} -
- } - /> - - - - {swapRecord.fee && ( - - {swapRecord.fee} - - {bsAggregator.blockchainServicesByName[swapRecord.account.blockchain].feeToken.symbol} - - - } - /> - )} - - - - {statusResponse.transactionHashes.map((hash, index, array) => { - const label = - index === 0 - ? t('transactionFromLabel') - : index + 1 === array.length - ? t('transactionToLabel') - : t('transactionAux') - - return ( - - - - {index + 1 !== array.length && } - - ) - })} -
- - - - ) -} diff --git a/src/renderer/src/store/reducers/AuthReducer.ts b/src/renderer/src/store/reducers/AuthReducer.ts index 1362e71f4..95101c224 100644 --- a/src/renderer/src/store/reducers/AuthReducer.ts +++ b/src/renderer/src/store/reducers/AuthReducer.ts @@ -231,8 +231,19 @@ const addPendingTransaction = createAsyncThunk< } }) -const addSwapRecord: CaseReducer> = (state, action) => { - state.data.swapRecords = [...state.data.swapRecords, action.payload] +const persistSwapRecord: CaseReducer> = (state, action) => { + const swapRecord = action.payload + + const index = state.data.swapRecords.findIndex( + it => it.swapId === swapRecord.swapId && it.swapProvider === swapRecord.swapProvider + ) + + if (index === -1) { + state.data.swapRecords = [...state.data.swapRecords, swapRecord] + return + } + + state.data.swapRecords[index] = swapRecord } const AuthReducer = createSlice({ @@ -245,7 +256,7 @@ const AuthReducer = createSlice({ deleteAccount, setCurrentLoginSession, resetTemporaryApplicationData, - addSwapRecord, + persistSwapRecord, }, extraReducers: builder => { builder.addCase(PURGE, () => initialState) diff --git a/src/shared/@types/i18next-resources.d.ts b/src/shared/@types/i18next-resources.d.ts index c4e98cabf..19a9c6d3a 100644 --- a/src/shared/@types/i18next-resources.d.ts +++ b/src/shared/@types/i18next-resources.d.ts @@ -777,6 +777,29 @@ interface Resources { connectedMessage: 'Detected your hardware wallet! Opening your wallet...' searchAgainButtonLabel: 'Search again' } + swapDetails: { + title: 'Your swap' + swapErrorMessage: ' Oops! We’ve encountered an error - swap failed' + transferErrorMessage: ' Oops! We’ve encountered an error - transfer failed' + subtitle: 'Your swap details' + refundedSubtitle: 'You’ve been refunded' + detailsHeaderLabel: 'Details' + detailsHeaderDescription: ' We aim to complete swaps in under 7 minutes' + statusPanelLabel: 'Status' + statusPanelSteps: ['Confirm', 'Exchange', 'Complete'] + routingPanelLabel: 'Routing' + routingPanelTransactionFromLabel: 'Transaction from' + routingPanelTransactionToLabel: 'Transaction to' + routingPanelTransactionToLabelPending: 'Pending...' + routingPanelTransactionFeeLabel: 'Transaction fee' + sentPanelLabel: 'You sent' + sentPanelTokenLabel: 'Token' + sentPanelAddressLabel: 'Sending address' + receivePanelLabel: 'You’ll receive' + receivePanelTokenLabel: 'Token' + receivePanelAddressLabel: 'Receiving address' + helpButtonLabel: 'Need help? Chat with us' + } } pages: { welcome: { @@ -1167,7 +1190,6 @@ interface Resources { } form: { title: 'What tokens do you want to swap?' - simpleSwapImgAlt: 'Simple swap' swapFromTitle: 'Swap this...' swapToTitle: 'For this...' balanceLabel: 'Balance' diff --git a/src/shared/@types/modal.ts b/src/shared/@types/modal.ts index 09ec97f36..8c4abf782 100644 --- a/src/shared/@types/modal.ts +++ b/src/shared/@types/modal.ts @@ -1,5 +1,5 @@ export type TRouteType = 'side' | 'center' -export type TRouterSize = 'sm' | 'md' | 'lg' | 'xl' +export type TRouterSize = 'sm' | 'md' | 'lg' | 'xl' | '1xl' export type TRoute = { element: JSX.Element diff --git a/src/shared/@types/store.ts b/src/shared/@types/store.ts index 4f6e676cf..58e77391b 100644 --- a/src/shared/@types/store.ts +++ b/src/shared/@types/store.ts @@ -91,15 +91,15 @@ export interface IContactState { export type TSwapRecord = { account: IAccountState - transactionHashes: string[] + txFrom?: string + txTo?: string swapProvider: 'simpleswap' - swapId: string + swapId?: string swapStatus: SwapServiceStatusResponse['status'] - tokenFrom: SwapServiceToken - tokenTo: SwapServiceToken + tokenFrom: SwapServiceToken + tokenTo: SwapServiceToken amountFrom: string amountTo: string addressTo: string - numberOfTransactions: number fee?: string }