From cf9792ddd744ed6494c42592f0c4d30420458b50 Mon Sep 17 00:00:00 2001 From: 0xwalde <109358247+0xwalde@users.noreply.github.com> Date: Thu, 12 Jan 2023 07:49:58 -0500 Subject: [PATCH 01/12] fix WBTC logo (#1875) * Add self-hosted WBTC logo and use it in currency icons * Put WBTC icon import in correct lexicographical order --- assets/png/currencies/WBTC.png | Bin 0 -> 5424 bytes utils/icons.ts | 2 ++ 2 files changed, 2 insertions(+) create mode 100644 assets/png/currencies/WBTC.png diff --git a/assets/png/currencies/WBTC.png b/assets/png/currencies/WBTC.png new file mode 100644 index 0000000000000000000000000000000000000000..5565d60c15ca3105f2454445876b62e4dac2ffb4 GIT binary patch literal 5424 zcmV-070>EYNk&E}6#xKNMM6+kP&iB+6#xJ)|G+;GuLq%#Bu7%znOPLa>*+nk^JaF6 zhT}+*93^|rLQNyZkele|Ed=AhsPlIZ;4X!A1fo_&7ik zQtAMt;Gm0w)%5QRcf3gMV|JPt}B%-^ICg`l3t-COUu{$B8H z&b}7~5xn0|Ma23K1@U-X6ha_~D9Yn`P>7&m{ve3c_Hn~CseW9St@wUklnNpBXcO70 z+qW?DzW?s``!il`qW}3JghDA_jrkv$+GyGYQ})&K{TvHa&;Lj!0}W!I*QFh~V4ztY z*(M1?B?}{oqD?8q_4^!7*zV%V25s_26Y3y=iNHJ%mfBWzhr%ET+ODD2v8$ zSc170Z9p6}tCp4DS1`wsy9<~y@9!_(P_{?meNwQenKq>+RHon&%tB)`zFEZer*wpmy~wzb`Zx8u@YJ9ak`Y`Sp(@Wedc% z$MSEvo{`D_x=;7NxBNS<=k(=Em&p)S39^oyRT}#fb0G zR*ida(|_-=&9~SVH!ZL8+b;EU?}47s5zbt5x#-@uI73%}>MgvYxl!F_QHRINPLnem)_ zkP$Dc&HT?avcG}!OF2?7#8j?4rLeEDJq&PaN;vW`kjidgzyJM^8e%!X&#-~oIwvC? zo!knD+eeg?8e@wU*H}!d>dZ(=TdOQ4-B4spjY^Mkmq~4GEg`m@yINAsiPgqb&ZBB$ z5+>E2c0`ER14@c@JMB`r zZ~t$Yc?@b}n*UYKE?pLFVjXEW;+%_d#lzmVz{j9+PA_a!{w|BlEgCTg4a+vRkoJX=>b-fGT&!& zdRkqG9s0+eq^IW=^-7qYWaTg|hVE_UuW)vDL^}WDSC_^SGKaQim}ud2Fq!@fvp??! zo*qZMA8JiAGT-s0YhEXcRC<7J@pR<_&qtbgUdpzyK4_^#YdModgRmiv{6`1ns>?jL zk|PayiSHQWOxixoRhrp=r>|w{@IKla>;Jm5(o&L^_OO2WLA;-FIY!#WFvrh69kCRp z#dpw|_2Dlu`t!^>)7ym8dP`wii)XXw0or)MBMZz7r&}$hsm7r*YYgJK0mj*-<@lbz z3%E)^y>3f0kOt^8QeIqA!kA-2Kl1z!tb96-fBHI?q@TSN+D>-FNa>)Z1KKv5!7t`d zp33Ct4lM#JPnOe3580R?JsRlVfKJ6tiS{^93rn53sUH0hBhL;)QRB~vA*{YPkmn$G{UT6%IYp($jyEj8Qn~eLN+6s;L;J z|F6=696eD7JrA=48-iXL5`kAh-bN{MF*M3VFe(Li^)Pk~SXbW*);R(S8SjQ#+1V%) z!Kehj83)Sjaw$5^kJm7Z6*TWwOJ6W6G9<0AN~tJP9u-t>$2_jCpblX=Fc%?C7Gla`7`v({VrdbJNmd8ueV!Fk#t9upUrKtpXJzD5jvYingdvEGECK1XN6c*n^cPD5NZX!X(H6sKDY= zvV^*DB05E=hqrhL8*pM)x@jGq!qo5Jdln$++sN&r!6TK_ zET#n#W;CCMq`OHgqCur~4KS~5nco;zmBw{6e`8zdR!q2&3w(W0i@kYy4)H-h)cXP(S%&D%be|c zFK|7oQO@QFa;m)#`imoaKv1BjgESu?kT1m-1bUHnyX6(G#B;U~=s~W;dIuSE#gRSM zZ+X(L8og4?<#U6cdtP5U_5h52f{Zz8q&e5}xUgruGH5nZv5Y}C8<4TbqwFpB5Kb4_ zMk}$#M;Fw}_p6c-76G=|tBH5Em5wxx-r#q&KLr5ukeHR?iaS&Bl@w2@Kd zb%5iM{ef~jfJv9Mnz)(sSY$t12{<142?9F-x1(K2RLXJJ3BCDV4~#q~rU17qO1T{h z;zqaaH=Q6B@FN-k$7_;895_xlD~D`jUkfp^m;~TQ)lqnlayyYfQzhJF`)S+p+!aZb z%kj+l6p){()R^hlT83%og|A~FA;k$~Hzf`58a3!7YygWWkdyA(LVSqOszMGVEqtV;cR~`xtv+E8?rGD!PLDPd6(hY*D-+Dr?CJdy8-$ixZu*|zu^Sh}u zVxD*3sMxqG?mlVsLMjBwYmXoXe33U$*WT%4+}-4s<3LDFx?UTIpgy z_`D>wBSnDByVWQ@@8*5JpfiW4^C-x?+Ybbe0`smts?Iz6#}P~V9fu>ilbUxW=iQO> z6w1Q;2PbA^`|e}ZMW@Q0cX3o1yENrN&ZC^7&bxeqoOkP{F1l10J_!WrcRc%%iv)&G zlb0O<=N;=+hTpji5G*^2)P+Zbd;^b!(ztQx(p=~6#cy9pd1hAN-d>PIlz>6^-aLM$ame{^-9A#0K4-XVk=AEbJ}MC ziVa!^GK_#OI|-Qg5yd1WxDX)8cjLj|z}rrul%Ucm;DHb?3efZev-BR=0`-ZgW4c5fU!b}8aaqa{siB56{9vt44@6L zkp{%;9-ad^@`xih>s+TSv_ttLO9khRw`I)xE{`G`8sr78gpCk9cM$F*z3zGVfp0^H znz(tn=Ay_x@8sK(pO43(4N@6R0VHjw(uYN@C$`XDCv(Fl;_sEIITz16)vifcD^%M= zkS(QgjJ-zy!f)uZPR<|S<~*Q;S2doAD)24wUI%`-K7|uMqV^?oO-{%a%Y;E z#?1+&-9-HxD}x?8)`vZ_$%7*eF@0gX6ly;};LQMmAIT;%`PM8RS{lMWu1BZY%;)a| zM%%Eb)(OXim%ov)w}UucO%&+2a7`h~F)xJ`Er-a%ysMG+WPrr8NHgSkc>a~O7R%MK z2S*~>PX`R$L|m_=ch6obc%uRBdcx@<+xT-=!_b3Ub)fmsih$Nc2&aqH29tFsQeA_hFU%rd>ty@R5@=#jX=Z4r z1EGgV!{7^CB!g*@PDuq=GNln=s348B=oDMI%f0A(m!Kj_zsOQez#m~Msgm|N1r*>r zth5P|m!e7$FJ8L}6)WiYUUUb}H{~@7dGX%kU_rC=hzj~Wkytq@=Dmw;)NA}`mKH(3 zB^4}%zjif2vvi1!*qicfR>@O9qYu+Vv-F2(2GhBdeDA8b*Dlv$D(A{&2iJ_tA$YdH zAY7&>%z$sS@6a96;0wZ!LM85dKs|(dXc@^t^{jS_(qX)ISzOU)gYPr1*BN3N+9Ia& znt)(peNqKvom-+WEM@#WNF92>$xlD{6y0uN-q*=;nc=kshR22Jyc7_C!D*UBdSA5r zr5B)~K?Es}Q+NT1se!p(Bd2V9-6G9?xSh$hAp((>C@0Ncz9!aYF8wKI%!_Eyldd2)%?d zphVOmUMKb!(?ouOIiV4Tx+GC?#jYsLnoC^~vM&ZtBt7FZWXM-hI!i30x#TP%g}mW0 zuf_KLnJ^XT7bAys@m-fQ(n>?%BF*zO?y4gerNHp>(m^fcG}8|TJ&tMdp_l#Q(j!pR z%~dY~Awi#>w!n3wP4M``Z^XU)lS@=bm4lCjmb)bK0S_?9h&gZ>#~`OcZN%6^LDGWv zu?H5W8OAxrckQ0qR-6YDb&pj2U;O8 zLw}@Ggv|HT-&j_bxEp7}%y{?c$;hCpVsJP_jOa_h3zWcn1NVjTpchp<09SQqctU^t zvpjKEngTO%#s0ZYZEn{RI!hIV^oP?NsUyQ=R;$Z3=?Ei>w$6Vdf}@|cKrqk}EAd9T zoC=cGdR-baL|{F}lcEkg3}6|Ru#n~f`*cSV#$TOfC#DI-4#82N)>X-Jx0oHun3mDM zf@DVaih#(@+k>20%H-e93W!?n3V&qh4kHM%x&d~UHSJ(Vf2u|$gvB)99$^i%*;(Gy z8)n7CjaAC!+uL$;&7DA&Eb*8(i&N+_2_&+8$jR_??TbK`JM}dJVUdI4a>&ox7Qn5W zkv$vpl*?tpgx12#=8)~+Te}7l=rETJU(V$>T%HD`m`X6??icLWZ5>A_|CJV>*z~X> z%TDOKow;6wcAiCJh&SucEmwuB#&x*$b04a+?uMhb#q5J`5iPMQK_@Ews@OJiSHmCK zdH7D17T+=Woy(MJw15g9rCSr#JgVhORwY~KWO-|xz4_lszW9=?3owz`-~~{3XY00v zSv5;l)pL3Yv(0pp_PFeDbN#Fe>n?!~Kp4=$#}Hl31BUVxULA5v$zRbnc^XuC9=SP-f08gSWSL?}&4O8GN8W-CZf zEpl+g)ci@smfn>0MO93&I_2R$$njSPEm1Z9nSg3k$l(>ttQVUcKNhi!xZ0N`uBLiS zusd{9b)wx7CfnY;I${}-wf<~CO)6Z)D!sK92L&r*%`It%Ydu2Ev1+bUcy)7=>X1#{ zEH`kbah^Drxh0j=s}rU8S4LfICa5 zuc3D3HMBBwv{ow4VR%88lczPY>O`EeMskinIjq4|M_y=L<}K`|*?(@Ft4`EPg~O~@ zo9y`E-xi3KXZpTBaAD^fTO`73ntHjm`TkWvLJQqZy1vgVdbp{U`zL6x@elVBt5@aO z-)M^V&JW&EfVtkIJDcLQ#w@evQ>|GOH#?7-dw+99Q2#^20gX}NUpZHD`fpZ$E7QLF zQ;9MC@NhtjbYN^!PM9Bcx+w9&)6y}_^ZH$pd1360erf)>&FSlz%I<#kbMNt9epvHs zaX;{J{%!AI@{bHH5KE39{_$JkKfw1U%q5x8?z3%$4B) literal 0 HcmV?d00001 diff --git a/utils/icons.ts b/utils/icons.ts index 479de74578..6cf5b2fd5c 100644 --- a/utils/icons.ts +++ b/utils/icons.ts @@ -29,6 +29,7 @@ import USDIcon from 'assets/png/currencies/sUSD.png'; import XAGIcon from 'assets/png/currencies/sXAG.png'; import XAUIcon from 'assets/png/currencies/sXAU.png'; import XMRIcon from 'assets/png/currencies/sXMR.png'; +import WBTCIcon from 'assets/png/currencies/WBTC.png'; import { CRYPTO_CURRENCY_MAP, SynthsName } from 'constants/currency'; import { FuturesMarketKey } from './futures'; @@ -68,4 +69,5 @@ export const SYNTH_ICONS: Record = sOP: OPIcon, KWENTA: KWENTAIcon, [CRYPTO_CURRENCY_MAP.SNX]: SNXIcon, + WBTC: WBTCIcon, }; From 4cd3fa77285ee6c2482f7772be1d4741a711cbdd Mon Sep 17 00:00:00 2001 From: "troyb.eth" Date: Thu, 12 Jan 2023 11:47:29 -0700 Subject: [PATCH 02/12] Leverage input regression (#1876) fix regression --- sections/futures/LeverageInput/LeverageInput.tsx | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/sections/futures/LeverageInput/LeverageInput.tsx b/sections/futures/LeverageInput/LeverageInput.tsx index d45498e4b6..c1a2cd1c14 100644 --- a/sections/futures/LeverageInput/LeverageInput.tsx +++ b/sections/futures/LeverageInput/LeverageInput.tsx @@ -36,16 +36,15 @@ const LeverageInput: FC = () => { const leverageInput = useAppSelector(selectIsolatedLeverageInput); const onLeverageChange = useCallback( - (newLeverage: number) => { + (newLeverage: string) => { const remainingMargin = position?.remainingMargin ?? zeroBN; const newTradeSize = marketPrice.eq(0) || remainingMargin.eq(0) ? '' - : wei(newLeverage).mul(remainingMargin).div(marketPrice).toString(); - const input = truncateNumbers(newLeverage, DEFAULT_FIAT_DECIMALS); - dispatch(setIsolatedMarginLeverageInput(input)); + : wei(Number(newLeverage)).mul(remainingMargin).div(marketPrice).toString(); const floored = floorNumber(Number(newTradeSize), 4); dispatch(editIsolatedMarginSize(String(floored), 'native')); + dispatch(setIsolatedMarginLeverageInput(newLeverage)); }, [position?.remainingMargin, marketPrice, dispatch] ); @@ -72,7 +71,7 @@ const LeverageInput: FC = () => { : 10; const truncateLeverage = useMemo( - () => truncateNumbers(wei(leverageInput ?? 0), DEFAULT_FIAT_DECIMALS), + () => truncateNumbers(wei(Number(leverageInput) ?? 0), DEFAULT_FIAT_DECIMALS), [leverageInput] ); @@ -98,7 +97,7 @@ const LeverageInput: FC = () => { maxValue={Number(truncateMaxLeverage)} value={Number(truncateLeverage)} onChange={(_, newValue) => { - onLeverageChange(newValue as number); + onLeverageChange(newValue.toString()); }} /> @@ -111,7 +110,7 @@ const LeverageInput: FC = () => { suffix="x" maxValue={maxLeverage.toNumber()} onChange={(_, newValue) => { - onLeverageChange(Number(newValue)); + onLeverageChange(newValue); }} disabled={isDisabled} /> @@ -121,7 +120,7 @@ const LeverageInput: FC = () => { mono variant="flat" onClick={() => { - onLeverageChange(Number(l)); + onLeverageChange(l); }} disabled={maxLeverage.lt(Number(l)) || marketInfo?.isSuspended} > From 90b46baeab87dcd722ac36a05385e57ba08346b9 Mon Sep 17 00:00:00 2001 From: Ralf Date: Fri, 13 Jan 2023 13:38:10 -0300 Subject: [PATCH 03/12] css: mobile fixes (#1883) --- sections/futures/MobileTrade/common.ts | 1 - sections/futures/PositionChart/PositionChart.tsx | 4 ++++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/sections/futures/MobileTrade/common.ts b/sections/futures/MobileTrade/common.ts index 67755d029c..c17f22be38 100644 --- a/sections/futures/MobileTrade/common.ts +++ b/sections/futures/MobileTrade/common.ts @@ -12,7 +12,6 @@ export const SectionTitle = styled.div` color: ${(props) => props.theme.colors.selectedTheme.yellow}; text-transform: uppercase; font-size: 13px; - text-shadow: 0px 1px 3px rgb(242, 242, 242); `; export const SectionSubTitle = styled.div` diff --git a/sections/futures/PositionChart/PositionChart.tsx b/sections/futures/PositionChart/PositionChart.tsx index c397e1d153..c12da9ac81 100644 --- a/sections/futures/PositionChart/PositionChart.tsx +++ b/sections/futures/PositionChart/PositionChart.tsx @@ -11,6 +11,7 @@ import { selectTradePreview, } from 'state/futures/selectors'; import { useAppSelector } from 'state/hooks'; +import media from 'styles/media'; export default function PositionChart() { const marketAsset = useAppSelector(selectMarketAsset); @@ -72,6 +73,9 @@ export default function PositionChart() { const Container = styled.div<{ visible: boolean }>` border: ${(props) => props.theme.colors.selectedTheme.border}; + ${media.lessThan('md')` + border: none; + `} border-radius: 10px; padding: 3px; min-height: 450px; From e63cc50326f33553abcd03a7e73c72f3eb8c6caa Mon Sep 17 00:00:00 2001 From: "troyb.eth" Date: Mon, 16 Jan 2023 15:48:05 -0700 Subject: [PATCH 04/12] Close position label (#1880) * make label close position * fix modal title --- .../Trade/DelayedOrderConfirmationModal.tsx | 21 +++++++++++++++++-- translations/en.json | 1 + 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/sections/futures/Trade/DelayedOrderConfirmationModal.tsx b/sections/futures/Trade/DelayedOrderConfirmationModal.tsx index 81b08fd6f7..64839ee32e 100644 --- a/sections/futures/Trade/DelayedOrderConfirmationModal.tsx +++ b/sections/futures/Trade/DelayedOrderConfirmationModal.tsx @@ -69,12 +69,21 @@ const DelayedOrderConfirmationModal: FC = () => { ); }, [nativeSizeDelta, orderType, dispatch]); - const positionSize = position?.position?.size ?? zeroBN; + const positionSize = useMemo(() => { + const positionDetails = position?.position; + return positionDetails + ? positionDetails.size.mul(positionDetails.side === PositionSide.LONG ? 1 : -1) + : zeroBN; + }, [position]); const orderDetails = useMemo(() => { return { nativeSizeDelta, size: (positionSize ?? zeroBN).add(nativeSizeDelta).abs() }; }, [nativeSizeDelta, positionSize]); + const isClosing = useMemo(() => { + return orderDetails.size.eq(zeroBN); + }, [orderDetails]); + // TODO: check this deposit const totalDeposit = useMemo(() => { return (commitDeposit ?? zeroBN).add(marketInfo?.keeperDeposit ?? zeroBN); @@ -172,7 +181,11 @@ const DelayedOrderConfirmationModal: FC = () => { {dataRows.map((row, i) => ( @@ -190,6 +203,8 @@ const DelayedOrderConfirmationModal: FC = () => { {submitting ? ( + ) : isClosing ? ( + t('futures.market.trade.confirmation.modal.close-order') ) : ( t('futures.market.trade.confirmation.modal.confirm-order') )} @@ -211,6 +226,8 @@ const DelayedOrderConfirmationModal: FC = () => { > {submitting ? ( + ) : isClosing ? ( + t('futures.market.trade.confirmation.modal.close-order') ) : ( t('futures.market.trade.confirmation.modal.confirm-order') )} diff --git a/translations/en.json b/translations/en.json index 0c90303200..51ac6406aa 100644 --- a/translations/en.json +++ b/translations/en.json @@ -808,6 +808,7 @@ "confirmation": { "modal": { "confirm-order": "Confirm order", + "close-order": "Close position", "max-leverage-disclaimer": "Note: A next price update could cause your order to exceed maximum leverage resulting in the order being dropped by the keeper.", "disabled-min-margin": "Minimum market margin of $50 required", "delayed-disclaimer": "* The deposit is applied to trading fees and keeper fees on order execution. If an order is either cancelled or not executed, the deposit will be forfeit to the Synthetix debt pool." From f5dd99447b0a6217dd819044d2879627125752b8 Mon Sep 17 00:00:00 2001 From: 0xwalde <109358247+0xwalde@users.noreply.github.com> Date: Tue, 17 Jan 2023 09:15:54 -0500 Subject: [PATCH 05/12] add anchors to sidebar links (#1882) * Replace NavButton with NavLink component using native anchors * Support disabled links --- components/Button/NavButton.tsx | 68 ------------------- components/Nav/NavLink.tsx | 57 ++++++++++++++++ .../DashboardLayout/DashboardLayout.tsx | 43 ++++-------- 3 files changed, 72 insertions(+), 96 deletions(-) delete mode 100644 components/Button/NavButton.tsx create mode 100644 components/Nav/NavLink.tsx diff --git a/components/Button/NavButton.tsx b/components/Button/NavButton.tsx deleted file mode 100644 index 5ca51e0a68..0000000000 --- a/components/Button/NavButton.tsx +++ /dev/null @@ -1,68 +0,0 @@ -import React from 'react'; -import styled from 'styled-components'; - -import Button from './Button'; - -type NavButtonProps = { - title: string; - isActive: boolean; - onClick?: React.MouseEventHandler | undefined; - disabled?: boolean; - noOutline?: boolean; -}; - -const NavButton: React.FC = ({ title, ...props }) => { - return ( -
- -

{title}

-
-
- ); -}; - -const StyledButton = styled(Button)` - height: initial; - display: flex; - - margin-top: 8px; - margin-bottom: 8px; - - padding-top: 10px; - padding-bottom: 10px; - - border: transparent; - background: ${(props) => - props.isActive ? props.theme.colors.selectedTheme.button.fill : 'transparent'}; - box-shadow: none; - border-radius: 100px; - - p { - margin: 0; - font-size: 15px; - text-align: left; - } - - .title { - color: ${(props) => - props.isActive - ? props.theme.colors.selectedTheme.button.text.primary - : props.theme.colors.selectedTheme.gray}; - } - - &:disabled { - background-color: transparent; - - p { - color: ${(props) => props.theme.colors.selectedTheme.button.tab.disabled.text}; - } - - border: transparent; - - .badge { - display: none; - } - } -`; - -export default NavButton; diff --git a/components/Nav/NavLink.tsx b/components/Nav/NavLink.tsx new file mode 100644 index 0000000000..c07ffa028e --- /dev/null +++ b/components/Nav/NavLink.tsx @@ -0,0 +1,57 @@ +import Link from 'next/link'; +import React from 'react'; +import styled from 'styled-components'; + +import { linkCSS } from 'styles/common'; + +type NavButtonProps = { + title: string; + isActive: boolean; + href: string; + disabled?: boolean; + external?: boolean; +}; + +const NavButton: React.FC = ({ title, href, external, disabled, ...props }) => { + return ( +
+ + + {title} + + +
+ ); +}; + +const StyledLink = styled.a<{ isActive: boolean; disabled?: boolean }>` + ${linkCSS}; + display: inline-block; + padding: 10px 14px; + margin: 8px 0; + font-family: ${(props) => props.theme.fonts.bold}; + font-size: 15px; + text-transform: capitalize; + border-radius: 100px; + background: ${(props) => + props.isActive ? props.theme.colors.selectedTheme.button.fill : 'transparent'}; + color: ${(props) => + props.isActive + ? props.theme.colors.selectedTheme.button.text.primary + : props.theme.colors.selectedTheme.gray}; + &:hover { + background: ${(props) => props.theme.colors.selectedTheme.button.fill}; + } + + &.disabled { + color: ${(props) => props.theme.colors.selectedTheme.button.disabled.text}; + background: transparent; + pointer-events: none; + } +`; + +export default NavButton; diff --git a/sections/dashboard/DashboardLayout/DashboardLayout.tsx b/sections/dashboard/DashboardLayout/DashboardLayout.tsx index c9b3747550..f5b6f72229 100644 --- a/sections/dashboard/DashboardLayout/DashboardLayout.tsx +++ b/sections/dashboard/DashboardLayout/DashboardLayout.tsx @@ -3,8 +3,8 @@ import { FC, useMemo } from 'react'; import { useTranslation } from 'react-i18next'; import styled from 'styled-components'; -import NavButton from 'components/Button/NavButton'; import { DesktopOnlyView, MobileOrTabletView } from 'components/Media'; +import NavLink from 'components/Nav/NavLink'; import { TabList, TabPanel } from 'components/Tab'; import { EXTERNAL_LINKS } from 'constants/links'; import ROUTES from 'constants/routes'; @@ -45,41 +45,42 @@ const DashboardLayout: FC = ({ children }) => { name: Tab.Overview, label: t('dashboard.tabs.overview'), active: activeTab === Tab.Overview, - onClick: () => router.push(ROUTES.Dashboard.Home), + href: ROUTES.Dashboard.Home, }, { name: Tab.History, label: t('dashboard.tabs.history'), active: activeTab === Tab.History, - onClick: () => router.push(ROUTES.Dashboard.History), + href: ROUTES.Dashboard.History, }, { name: Tab.Markets, label: t('dashboard.tabs.markets'), active: activeTab === Tab.Markets, disabled: false, - onClick: () => router.push(ROUTES.Dashboard.Markets), + href: ROUTES.Dashboard.Markets, }, { name: Tab.Stake, label: t('dashboard.tabs.staking'), active: activeTab === Tab.Stake, - onClick: () => router.push(ROUTES.Dashboard.Stake), + href: ROUTES.Dashboard.Stake, }, { name: Tab.Earn, label: t('dashboard.tabs.earn'), active: activeTab === Tab.Earn, - onClick: () => router.push(ROUTES.Dashboard.Earn), + href: ROUTES.Dashboard.Earn, }, { name: Tab.Governance, label: t('dashboard.tabs.governance'), active: activeTab === Tab.Governance, - onClick: () => window.open(EXTERNAL_LINKS.Governance.Vote, '_blank'), + href: EXTERNAL_LINKS.Governance.Vote, + external: true, }, ], - [t, activeTab, router] + [t, activeTab] ); return ( @@ -90,31 +91,17 @@ const DashboardLayout: FC = ({ children }) => { {t('dashboard.titles.trading')} - {TABS.slice(0, 3).map(({ name, label, active, disabled, onClick }) => ( - + {TABS.slice(0, 3).map(({ name, label, active, ...rest }) => ( + {label} - + ))} {t('dashboard.titles.community')} - {TABS.slice(3).map(({ name, label, active, disabled, onClick }) => ( - + {TABS.slice(3).map(({ name, label, active, ...rest }) => ( + {label} - + ))} From 43d8feb9ca00446592af8ed5ce193574d9adbca9 Mon Sep 17 00:00:00 2001 From: "troyb.eth" Date: Wed, 18 Jan 2023 04:09:50 -0700 Subject: [PATCH 06/12] fix: funding rate display (#1891) * correct funding * correct table --- sections/dashboard/FuturesMarketsTable/FuturesMarketsTable.tsx | 2 +- sections/futures/MarketDetails/useGetMarketData.ts | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/sections/dashboard/FuturesMarketsTable/FuturesMarketsTable.tsx b/sections/dashboard/FuturesMarketsTable/FuturesMarketsTable.tsx index 589565b2a3..9d0cdff1fc 100644 --- a/sections/dashboard/FuturesMarketsTable/FuturesMarketsTable.tsx +++ b/sections/dashboard/FuturesMarketsTable/FuturesMarketsTable.tsx @@ -48,7 +48,7 @@ const FuturesMarketsTable: FC = () => { volume: volume?.toNumber() ?? 0, pastPrice: pastPrice?.price, priceChange: pastPrice?.price && marketPrice.sub(pastPrice?.price).div(marketPrice), - fundingRate: market.currentFundingRate ?? null, + fundingRate: market.currentFundingRate.div(marketPrice) ?? null, openInterest: market.marketSize.mul(marketPrice), openInterestNative: market.marketSize, longInterest: market.marketSize.add(market.marketSkew).div('2').abs().mul(marketPrice), diff --git a/sections/futures/MarketDetails/useGetMarketData.ts b/sections/futures/MarketDetails/useGetMarketData.ts index be49ec8098..bffcd06882 100644 --- a/sections/futures/MarketDetails/useGetMarketData.ts +++ b/sections/futures/MarketDetails/useGetMarketData.ts @@ -49,7 +49,8 @@ const useGetMarketData = (mobile?: boolean) => { const oraclePrice = marketPrices.onChain ?? wei(0); const data: MarketData = useMemo(() => { - const fundingValue = marketInfo?.currentFundingRate; + // TODO: remove this hard-coded display fix for funding + const fundingValue = marketInfo?.currentFundingRate.div(oraclePrice); const marketName = `${marketInfo?.marketName ?? t('futures.market.info.default-market')}`; From 3e6953d0979b5e622a48eac23c35e7d3f7dbe1d2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 18 Jan 2023 08:50:14 -0300 Subject: [PATCH 07/12] Bump @typescript-eslint/eslint-plugin from 5.47.0 to 5.48.2 (#1890) * Bump @typescript-eslint/eslint-plugin from 5.47.0 to 5.48.2 Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 5.47.0 to 5.48.2. - [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases) - [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md) - [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v5.48.2/packages/eslint-plugin) --- updated-dependencies: - dependency-name: "@typescript-eslint/eslint-plugin" dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * fix package lock Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 754 +++++++++++----------------------------------- package.json | 2 +- 2 files changed, 177 insertions(+), 579 deletions(-) diff --git a/package-lock.json b/package-lock.json index 68c39241ac..0121d3c9a7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -105,7 +105,7 @@ "@types/react-table": "7.0.22", "@types/redux-logger": "^3.0.9", "@types/styled-components": "5.1.2", - "@typescript-eslint/eslint-plugin": "5.47.0", + "@typescript-eslint/eslint-plugin": "5.48.2", "@typescript-eslint/parser": "5.40.1", "babel-eslint": "10.1.0", "eslint": "7.32.0", @@ -2918,22 +2918,6 @@ "node": "^10.12.0 || >=12.0.0" } }, - "node_modules/@eslint/eslintrc/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, "node_modules/@eslint/eslintrc/node_modules/globals": { "version": "13.19.0", "resolved": "https://registry.npmjs.org/globals/-/globals-13.19.0.tgz", @@ -2958,12 +2942,6 @@ "node": ">= 4" } }, - "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, "node_modules/@eth-optimism/contracts": { "version": "0.5.37", "resolved": "https://registry.npmjs.org/@eth-optimism/contracts/-/contracts-0.5.37.tgz", @@ -5956,34 +5934,6 @@ "node": ">=10.10.0" } }, - "node_modules/@microsoft/eslint-formatter-sarif/node_modules/acorn": { - "version": "8.8.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", - "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/@microsoft/eslint-formatter-sarif/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, "node_modules/@microsoft/eslint-formatter-sarif/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -6185,12 +6135,6 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/@microsoft/eslint-formatter-sarif/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, "node_modules/@microsoft/eslint-formatter-sarif/node_modules/optionator": { "version": "0.9.1", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", @@ -7104,6 +7048,26 @@ "node": ">=14" } }, + "node_modules/@snapshot-labs/snapshot.js/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@snapshot-labs/snapshot.js/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, "node_modules/@solana/buffer-layout": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@solana/buffer-layout/-/buffer-layout-4.0.1.tgz", @@ -9559,22 +9523,6 @@ "node": ">=0.4.0" } }, - "node_modules/@storybook/builder-webpack4/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, "node_modules/@storybook/builder-webpack4/node_modules/ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", @@ -10013,12 +9961,6 @@ "node": ">= 10.13.0" } }, - "node_modules/@storybook/builder-webpack4/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, "node_modules/@storybook/builder-webpack4/node_modules/loader-runner": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", @@ -11160,22 +11102,6 @@ "node": ">=0.4.0" } }, - "node_modules/@storybook/builder-webpack5/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, "node_modules/@storybook/builder-webpack5/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -11503,12 +11429,6 @@ "node": ">=4" } }, - "node_modules/@storybook/builder-webpack5/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, "node_modules/@storybook/builder-webpack5/node_modules/loader-runner": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", @@ -12265,22 +12185,6 @@ "node": ">=0.4.0" } }, - "node_modules/@storybook/core-common/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, "node_modules/@storybook/core-common/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -12541,12 +12445,6 @@ "node": ">=4" } }, - "node_modules/@storybook/core-common/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, "node_modules/@storybook/core-common/node_modules/loader-runner": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", @@ -13172,22 +13070,6 @@ "node": ">=0.4.0" } }, - "node_modules/@storybook/core-server/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, "node_modules/@storybook/core-server/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -13442,12 +13324,6 @@ "node": ">=4" } }, - "node_modules/@storybook/core-server/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, "node_modules/@storybook/core-server/node_modules/loader-runner": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", @@ -14108,22 +13984,6 @@ "node": ">=0.4.0" } }, - "node_modules/@storybook/manager-webpack4/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, "node_modules/@storybook/manager-webpack4/node_modules/ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", @@ -14534,12 +14394,6 @@ "node": ">= 10.13.0" } }, - "node_modules/@storybook/manager-webpack4/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, "node_modules/@storybook/manager-webpack4/node_modules/loader-runner": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", @@ -15562,22 +15416,6 @@ "node": ">=0.4.0" } }, - "node_modules/@storybook/manager-webpack5/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, "node_modules/@storybook/manager-webpack5/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -15905,12 +15743,6 @@ "node": ">=4" } }, - "node_modules/@storybook/manager-webpack5/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, "node_modules/@storybook/manager-webpack5/node_modules/loader-runner": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", @@ -16964,20 +16796,16 @@ "@xtuc/long": "4.2.2" } }, - "node_modules/@storybook/react/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "node_modules/@storybook/react/node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "bin": { + "acorn": "bin/acorn" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "engines": { + "node": ">=0.4.0" } }, "node_modules/@storybook/react/node_modules/ansi-styles": { @@ -17240,12 +17068,6 @@ "node": ">=4" } }, - "node_modules/@storybook/react/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, "node_modules/@storybook/react/node_modules/loader-runner": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", @@ -18235,22 +18057,6 @@ "node": ">=0.4.0" } }, - "node_modules/@storybook/telemetry/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, "node_modules/@storybook/telemetry/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -18511,12 +18317,6 @@ "node": ">=4" } }, - "node_modules/@storybook/telemetry/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, "node_modules/@storybook/telemetry/node_modules/loader-runner": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", @@ -19703,6 +19503,18 @@ } } }, + "node_modules/@synthetixio/synpress/node_modules/eslint-plugin-promise": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-6.0.0.tgz", + "integrity": "sha512-7GPezalm5Bfi/E22PnQxDWH2iW9GTvAlUNTztemeHb6c1BniSyoeTrM87JkC0wYdi6aQrZX9p2qEiAno8aTcbw==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, "node_modules/@synthetixio/synpress/node_modules/eslint-plugin-testing-library": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/eslint-plugin-testing-library/-/eslint-plugin-testing-library-5.2.1.tgz", @@ -20342,30 +20154,6 @@ "debug": "^4.3.1" } }, - "node_modules/@truffle/contract-schema/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "optional": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/@truffle/contract-schema/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true, - "optional": true - }, "node_modules/@truffle/contract/node_modules/bignumber.js": { "version": "7.2.1", "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-7.2.1.tgz", @@ -21514,14 +21302,14 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.47.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.47.0.tgz", - "integrity": "sha512-AHZtlXAMGkDmyLuLZsRpH3p4G/1iARIwc/T0vIem2YB+xW6pZaXYXzCBnZSF/5fdM97R9QqZWZ+h3iW10XgevQ==", + "version": "5.48.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.48.2.tgz", + "integrity": "sha512-sR0Gja9Ky1teIq4qJOl0nC+Tk64/uYdX+mi+5iB//MH8gwyx8e3SOyhEzeLZEFEEfCaLf8KJq+Bd/6je1t+CAg==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.47.0", - "@typescript-eslint/type-utils": "5.47.0", - "@typescript-eslint/utils": "5.47.0", + "@typescript-eslint/scope-manager": "5.48.2", + "@typescript-eslint/type-utils": "5.48.2", + "@typescript-eslint/utils": "5.48.2", "debug": "^4.3.4", "ignore": "^5.2.0", "natural-compare-lite": "^1.4.0", @@ -21793,13 +21581,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "5.47.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.47.0.tgz", - "integrity": "sha512-dvJab4bFf7JVvjPuh3sfBUWsiD73aiftKBpWSfi3sUkysDQ4W8x+ZcFpNp7Kgv0weldhpmMOZBjx1wKN8uWvAw==", + "version": "5.48.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.48.2.tgz", + "integrity": "sha512-zEUFfonQid5KRDKoI3O+uP1GnrFd4tIHlvs+sTJXiWuypUWMuDaottkJuR612wQfOkjYbsaskSIURV9xo4f+Fw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.47.0", - "@typescript-eslint/visitor-keys": "5.47.0" + "@typescript-eslint/types": "5.48.2", + "@typescript-eslint/visitor-keys": "5.48.2" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -21810,9 +21598,9 @@ } }, "node_modules/@typescript-eslint/scope-manager/node_modules/@typescript-eslint/types": { - "version": "5.47.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.47.0.tgz", - "integrity": "sha512-eslFG0Qy8wpGzDdYKu58CEr3WLkjwC5Usa6XbuV89ce/yN5RITLe1O8e+WFEuxnfftHiJImkkOBADj58ahRxSg==", + "version": "5.48.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.48.2.tgz", + "integrity": "sha512-hE7dA77xxu7ByBc6KCzikgfRyBCTst6dZQpwaTy25iMYOnbNljDT4hjhrGEJJ0QoMjrfqrx+j1l1B9/LtKeuqA==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -21823,13 +21611,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "5.47.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.47.0.tgz", - "integrity": "sha512-1J+DFFrYoDUXQE1b7QjrNGARZE6uVhBqIvdaXTe5IN+NmEyD68qXR1qX1g2u4voA+nCaelQyG8w30SAOihhEYg==", + "version": "5.48.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.48.2.tgz", + "integrity": "sha512-QVWx7J5sPMRiOMJp5dYshPxABRoZV1xbRirqSk8yuIIsu0nvMTZesKErEA3Oix1k+uvsk8Cs8TGJ6kQ0ndAcew==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "5.47.0", - "@typescript-eslint/utils": "5.47.0", + "@typescript-eslint/typescript-estree": "5.48.2", + "@typescript-eslint/utils": "5.48.2", "debug": "^4.3.4", "tsutils": "^3.21.0" }, @@ -21850,9 +21638,9 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { - "version": "5.47.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.47.0.tgz", - "integrity": "sha512-eslFG0Qy8wpGzDdYKu58CEr3WLkjwC5Usa6XbuV89ce/yN5RITLe1O8e+WFEuxnfftHiJImkkOBADj58ahRxSg==", + "version": "5.48.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.48.2.tgz", + "integrity": "sha512-hE7dA77xxu7ByBc6KCzikgfRyBCTst6dZQpwaTy25iMYOnbNljDT4hjhrGEJJ0QoMjrfqrx+j1l1B9/LtKeuqA==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -21863,13 +21651,13 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "5.47.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.47.0.tgz", - "integrity": "sha512-LxfKCG4bsRGq60Sqqu+34QT5qT2TEAHvSCCJ321uBWywgE2dS0LKcu5u+3sMGo+Vy9UmLOhdTw5JHzePV/1y4Q==", + "version": "5.48.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.48.2.tgz", + "integrity": "sha512-bibvD3z6ilnoVxUBFEgkO0k0aFvUc4Cttt0dAreEr+nrAHhWzkO83PEVVuieK3DqcgL6VAK5dkzK8XUVja5Zcg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.47.0", - "@typescript-eslint/visitor-keys": "5.47.0", + "@typescript-eslint/types": "5.48.2", + "@typescript-eslint/visitor-keys": "5.48.2", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -22013,16 +21801,16 @@ "dev": true }, "node_modules/@typescript-eslint/utils": { - "version": "5.47.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.47.0.tgz", - "integrity": "sha512-U9xcc0N7xINrCdGVPwABjbAKqx4GK67xuMV87toI+HUqgXj26m6RBp9UshEXcTrgCkdGYFzgKLt8kxu49RilDw==", + "version": "5.48.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.48.2.tgz", + "integrity": "sha512-2h18c0d7jgkw6tdKTlNaM7wyopbLRBiit8oAxoP89YnuBOzCZ8g8aBCaCqq7h208qUTroL7Whgzam7UY3HVLow==", "dev": true, "dependencies": { "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.47.0", - "@typescript-eslint/types": "5.47.0", - "@typescript-eslint/typescript-estree": "5.47.0", + "@typescript-eslint/scope-manager": "5.48.2", + "@typescript-eslint/types": "5.48.2", + "@typescript-eslint/typescript-estree": "5.48.2", "eslint-scope": "^5.1.1", "eslint-utils": "^3.0.0", "semver": "^7.3.7" @@ -22039,9 +21827,9 @@ } }, "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/types": { - "version": "5.47.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.47.0.tgz", - "integrity": "sha512-eslFG0Qy8wpGzDdYKu58CEr3WLkjwC5Usa6XbuV89ce/yN5RITLe1O8e+WFEuxnfftHiJImkkOBADj58ahRxSg==", + "version": "5.48.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.48.2.tgz", + "integrity": "sha512-hE7dA77xxu7ByBc6KCzikgfRyBCTst6dZQpwaTy25iMYOnbNljDT4hjhrGEJJ0QoMjrfqrx+j1l1B9/LtKeuqA==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -22052,13 +21840,13 @@ } }, "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "5.47.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.47.0.tgz", - "integrity": "sha512-LxfKCG4bsRGq60Sqqu+34QT5qT2TEAHvSCCJ321uBWywgE2dS0LKcu5u+3sMGo+Vy9UmLOhdTw5JHzePV/1y4Q==", + "version": "5.48.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.48.2.tgz", + "integrity": "sha512-bibvD3z6ilnoVxUBFEgkO0k0aFvUc4Cttt0dAreEr+nrAHhWzkO83PEVVuieK3DqcgL6VAK5dkzK8XUVja5Zcg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.47.0", - "@typescript-eslint/visitor-keys": "5.47.0", + "@typescript-eslint/types": "5.48.2", + "@typescript-eslint/visitor-keys": "5.48.2", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -22112,12 +21900,12 @@ "dev": true }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.47.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.47.0.tgz", - "integrity": "sha512-ByPi5iMa6QqDXe/GmT/hR6MZtVPi0SqMQPDx15FczCBXJo/7M8T88xReOALAfpBLm+zxpPfmhuEvPb577JRAEg==", + "version": "5.48.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.48.2.tgz", + "integrity": "sha512-z9njZLSkwmjFWUelGEwEbdf4NwKvfHxvGC0OcGN1Hp/XNDIcJ7D5DpPNPv6x6/mFvc1tQHsaWmpD/a4gOvvCJQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.47.0", + "@typescript-eslint/types": "5.48.2", "eslint-visitor-keys": "^3.3.0" }, "engines": { @@ -22129,9 +21917,9 @@ } }, "node_modules/@typescript-eslint/visitor-keys/node_modules/@typescript-eslint/types": { - "version": "5.47.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.47.0.tgz", - "integrity": "sha512-eslFG0Qy8wpGzDdYKu58CEr3WLkjwC5Usa6XbuV89ce/yN5RITLe1O8e+WFEuxnfftHiJImkkOBADj58ahRxSg==", + "version": "5.48.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.48.2.tgz", + "integrity": "sha512-hE7dA77xxu7ByBc6KCzikgfRyBCTst6dZQpwaTy25iMYOnbNljDT4hjhrGEJJ0QoMjrfqrx+j1l1B9/LtKeuqA==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -23203,9 +22991,9 @@ } }, "node_modules/acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", + "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -23224,6 +23012,18 @@ "acorn-walk": "^7.1.1" } }, + "node_modules/acorn-globals/node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/acorn-import-assertions": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", @@ -23253,6 +23053,18 @@ "xtend": "^4.0.2" } }, + "node_modules/acorn-node/node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/acorn-walk": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", @@ -23353,13 +23165,13 @@ } }, "node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dependencies": { "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" }, "funding": { @@ -23391,6 +23203,26 @@ } } }, + "node_modules/ajv-formats/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, "node_modules/ajv-keywords": { "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", @@ -24661,22 +24493,6 @@ "webpack": ">=2" } }, - "node_modules/babel-loader/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, "node_modules/babel-loader/node_modules/find-cache-dir": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", @@ -24707,12 +24523,6 @@ "node": ">=8" } }, - "node_modules/babel-loader/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, "node_modules/babel-loader/node_modules/locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", @@ -29799,22 +29609,6 @@ "webpack": "^4.0.0 || ^5.0.0" } }, - "node_modules/css-loader/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, "node_modules/css-loader/node_modules/big.js": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", @@ -29833,12 +29627,6 @@ "node": ">=6" } }, - "node_modules/css-loader/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, "node_modules/css-loader/node_modules/json5": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", @@ -32189,18 +31977,6 @@ } } }, - "node_modules/eslint-plugin-promise": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-6.0.0.tgz", - "integrity": "sha512-7GPezalm5Bfi/E22PnQxDWH2iW9GTvAlUNTztemeHb6c1BniSyoeTrM87JkC0wYdi6aQrZX9p2qEiAno8aTcbw==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" - } - }, "node_modules/eslint-plugin-react": { "version": "7.21.5", "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.21.5.tgz", @@ -32436,22 +32212,6 @@ "@babel/highlight": "^7.10.4" } }, - "node_modules/eslint/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, "node_modules/eslint/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -32579,12 +32339,6 @@ "node": ">= 4" } }, - "node_modules/eslint/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, "node_modules/eslint/node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -32661,6 +32415,18 @@ "node": "^10.12.0 || >=12.0.0" } }, + "node_modules/espree/node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/espree/node_modules/eslint-visitor-keys": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", @@ -35261,22 +35027,6 @@ } } }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, "node_modules/fork-ts-checker-webpack-plugin/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -35351,12 +35101,6 @@ "node": ">=8" } }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, "node_modules/fork-ts-checker-webpack-plugin/node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -36174,28 +35918,6 @@ "node": ">=6" } }, - "node_modules/har-validator/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/har-validator/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, "node_modules/has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -42602,18 +42324,6 @@ } } }, - "node_modules/jsdom/node_modules/acorn": { - "version": "8.8.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", - "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/jsdom/node_modules/form-data": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", @@ -42751,9 +42461,9 @@ "dev": true }, "node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" }, "node_modules/json-stable-stringify": { "version": "0.0.1", @@ -45464,21 +45174,6 @@ "url-loader": "^1.1.2" } }, - "node_modules/next-optimized-images/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, "node_modules/next-optimized-images/node_modules/big.js": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", @@ -45502,11 +45197,6 @@ "webpack": "^4.0.0" } }, - "node_modules/next-optimized-images/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" - }, "node_modules/next-optimized-images/node_modules/json5": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", @@ -50880,28 +50570,6 @@ "url": "https://opencollective.com/webpack" } }, - "node_modules/schema-utils/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/schema-utils/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, "node_modules/scrypt-js": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-3.0.1.tgz", @@ -51222,22 +50890,6 @@ "node": ">= 0.8.0" } }, - "node_modules/serve/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, "node_modules/serve/node_modules/chalk": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", @@ -51279,12 +50931,6 @@ "ms": "2.0.0" } }, - "node_modules/serve/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, "node_modules/serve/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -53010,28 +52656,6 @@ "webpack": "^4.0.0 || ^5.0.0" } }, - "node_modules/style-loader/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/style-loader/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, "node_modules/style-loader/node_modules/schema-utils": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", @@ -53880,6 +53504,21 @@ "node": ">=8" } }, + "node_modules/table/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, "node_modules/table/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -53918,6 +53557,11 @@ "node": ">=8" } }, + "node_modules/table/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, "node_modules/table/node_modules/slice-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", @@ -54293,18 +53937,6 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/terser/node_modules/acorn": { - "version": "8.8.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", - "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/terser/node_modules/commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", @@ -55811,28 +55443,6 @@ } } }, - "node_modules/url-loader/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/url-loader/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, "node_modules/url-loader/node_modules/schema-utils": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", @@ -58332,18 +57942,6 @@ "integrity": "sha512-5tyDlKLqPfMqjT3Q9TAqf2YqjwmnUleZwzJi1A5qXnlBCdj2AtOJ6wAWdglTIDOPgOiOrXeBeFcsQ8+aGQ6QbA==", "dev": true }, - "node_modules/webpack/node_modules/acorn": { - "version": "8.8.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", - "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/webpack/node_modules/tapable": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", diff --git a/package.json b/package.json index ade37ef539..341d510f14 100644 --- a/package.json +++ b/package.json @@ -121,7 +121,7 @@ "@types/react-table": "7.0.22", "@types/redux-logger": "^3.0.9", "@types/styled-components": "5.1.2", - "@typescript-eslint/eslint-plugin": "5.47.0", + "@typescript-eslint/eslint-plugin": "5.48.2", "@typescript-eslint/parser": "5.40.1", "babel-eslint": "10.1.0", "eslint": "7.32.0", From de8c88a33bce29c4dc7d2ea971941442d7065c88 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 18 Jan 2023 09:03:27 -0300 Subject: [PATCH 08/12] Bump html-to-image from 1.11.3 to 1.11.4 (#1862) * Bump html-to-image from 1.11.3 to 1.11.4 Bumps [html-to-image](https://github.com/bubkoo/html-to-image) from 1.11.3 to 1.11.4. - [Release notes](https://github.com/bubkoo/html-to-image/releases) - [Changelog](https://github.com/bubkoo/html-to-image/blob/master/CHANGELOG.md) - [Commits](https://github.com/bubkoo/html-to-image/compare/v1.11.3...v1.11.4) --- updated-dependencies: - dependency-name: html-to-image dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * fix package lock Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: platschi --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0121d3c9a7..32185914be 100644 --- a/package-lock.json +++ b/package-lock.json @@ -121,7 +121,7 @@ "eslint-plugin-react-hooks": "4.6.0", "eslint-plugin-testing-library": "^5.1.0", "eslint-plugin-ui-testing": "^2.0.0", - "html-to-image": "1.11.3", + "html-to-image": "1.11.4", "husky": "8.0.1", "jest": "28.1.0", "jest-environment-jsdom": "28.1.0", @@ -36489,9 +36489,9 @@ } }, "node_modules/html-to-image": { - "version": "1.11.3", - "resolved": "https://registry.npmjs.org/html-to-image/-/html-to-image-1.11.3.tgz", - "integrity": "sha512-9E/uinAx0LrfGndny36FDh3j3shpp0vn/J1UFvpYZm/y6n8CjWJ+h6jyU1VzmOKAx/Fy/NPGath7nmRMpaocmg==", + "version": "1.11.4", + "resolved": "https://registry.npmjs.org/html-to-image/-/html-to-image-1.11.4.tgz", + "integrity": "sha512-I6jeGpjSI/pea+p/8q6HAWPxptZkEYaZ40ZLnpCHuhCJJnUHQ/YzMEQMNY/KMdPZJ4+GJIwo9dnJy76eW9p9cg==", "dev": true }, "node_modules/html-void-elements": { diff --git a/package.json b/package.json index 341d510f14..50093a1f04 100644 --- a/package.json +++ b/package.json @@ -137,7 +137,7 @@ "eslint-plugin-react-hooks": "4.6.0", "eslint-plugin-testing-library": "^5.1.0", "eslint-plugin-ui-testing": "^2.0.0", - "html-to-image": "1.11.3", + "html-to-image": "1.11.4", "husky": "8.0.1", "jest": "28.1.0", "jest-environment-jsdom": "28.1.0", From 801ded04dd9a5e671a2d82ec671eac33bdf97e79 Mon Sep 17 00:00:00 2001 From: Oluwakorede Fashokun Date: Mon, 23 Jan 2023 08:12:20 -0500 Subject: [PATCH 09/12] component refactor (part 3) (#1842) * Clean up Card ts-ignore * Small changes * Amalgamate * Fix prop and things * Small changes * Cleanup * Delete unused components * Fix SSR * Renaming and deleting * Remove more things * Fix issue with fragment * Remove homepage section barrel files * Fix BalanceActions * More memos * Remove constant from within component * Move files in leaderboard folder * More deletions * Flip RND * Add more memos * Grid and Flex * Generalize SplitContainer * More fixes * MarketClosureIcon memo * Remove many common folders * Remove domain-specific components from components folder * Update to match review requirements * Add TableHeader * ExternalLink changes * Check color on value * Remove CSS vars * Switch inputs to type text * Apply requested fixes * Maybe this? * Add yellow color * Fix pending * Fix fonts * Fix KWENTA logo margin --- components/Badge/MarketBadge.tsx | 52 ++- components/BaseModal/BaseModal.tsx | 68 +-- components/Button/TabButton.tsx | 4 +- components/Card/Card.tsx | 14 +- components/Card/CardBody.tsx | 2 +- components/Card/CardHeader.tsx | 4 +- components/Card/index.ts | 2 + components/ChangePercent/ChangePercent.tsx | 47 +-- components/Checkbox/Checkbox.tsx | 15 +- .../CurrencyAmount/CurrencyAmount.tsx | 61 +-- .../Currency/CurrencyIcon/TokenIcon.tsx | 8 +- .../Currency/CurrencyName/CurrencyName.tsx | 80 ++-- .../Currency/CurrencyPrice/CurrencyPrice.tsx | 83 ++-- components/Currency/common.tsx | 4 - components/Error/index.ts | 1 - .../Error.tsx => ErrorView/ErrorView.tsx} | 64 ++- components/ErrorView/index.ts | 1 + .../FullScreenModal/FullScreenModal.tsx | 24 +- components/InfoBox/InfoBox.tsx | 147 +++---- components/Input/CustomInput.tsx | 92 ++--- components/Input/CustomNumericInput.tsx | 100 +++-- components/Input/InputBalanceLabel.tsx | 2 +- components/Input/NumericInput.tsx | 72 ++-- components/Loader/Loader.tsx | 26 +- .../MarketClosureIcon/MarketClosureIcon.tsx | 44 +- components/Nav/DropDownLabel.tsx | 2 +- .../PoweredBySynthetix/PoweredBySynthetix.tsx | 7 +- components/PreviewArrow/PreviewArrow.tsx | 22 +- components/ProgressBar/ProgressBar.tsx | 25 -- components/ProgressBar/index.ts | 1 - components/ProgressSteps/ProgressSteps.tsx | 6 +- components/README.md | 3 + components/StakeCard/StakeCard.tsx | 11 +- components/Table/Pagination.tsx | 3 +- components/Table/Table.tsx | 14 +- components/Table/TableBodyRow.tsx | 2 +- components/Table/index.ts | 2 +- components/Text/Body.tsx | 19 +- components/Text/Heading.tsx | 14 +- components/Text/LogoText.tsx | 4 +- .../{TooltipStyles.tsx => BaseTooltip.tsx} | 4 +- components/Tooltip/ErrorTooltip.ts | 2 +- components/Tooltip/TimerTooltip.tsx | 26 +- .../{StyledTooltip.tsx => Tooltip.tsx} | 30 +- .../TransactionNotification.tsx | 2 +- components/layout/flex.ts | 25 ++ components/layout/grid.ts | 34 ++ .../common.tsx => components/layout/modals.ts | 2 +- constants/NotificationContainer.tsx | 2 +- constants/competition.ts | 8 + constants/menu.ts | 3 + constants/routes.ts | 14 + containers/index.tsx | 13 - package-lock.json | 52 ++- pages/404.tsx | 2 +- pages/_app.tsx | 5 +- pages/dashboard/earn.tsx | 2 +- pages/market.tsx | 8 +- queries/rates/useCandlesticksQuery.ts | 4 +- queries/rates/utils.ts | 6 +- .../useGetSynthsTradingVolumeForAllMarkets.ts | 2 +- queries/synths/utils.ts | 2 +- sections/app/AcknowledgementModal.tsx | 2 +- .../dashboard/Deprecated/RedeemTxModal.tsx | 7 +- .../FuturesHistoryTable.tsx | 15 +- .../FuturesMarketsTable.tsx | 53 ++- .../FuturesPositionsTable.tsx | 18 +- .../MobilePositionRow.tsx | 12 +- .../FuturesPositionsTable/constants.ts | 18 - .../MobileDashboard/FuturesMarkets.tsx | 33 +- .../MobileDashboard/MobileDashboard.tsx | 3 +- .../MobileDashboard/OpenPositions.tsx | 19 +- .../dashboard/MobileDashboard/Portfolio.tsx | 2 +- .../dashboard/MobileDashboard/SpotMarkets.tsx | 4 +- sections/dashboard/MobileDashboard/common.ts | 30 -- sections/dashboard/Overview/Overview.tsx | 14 +- .../PortfolioChart/PortfolioChart.tsx | 13 +- .../SpotHistoryTable/SpotHistoryTable.tsx | 21 +- .../SpotMarketsTable/SpotMarketsTable.tsx | 12 +- sections/dashboard/Stake/EscrowTable.tsx | 38 +- .../Stake/InputCards/RedeemInputCard.tsx | 6 +- sections/dashboard/Stake/RedemptionTab.tsx | 27 +- sections/dashboard/Stake/StakingPortfolio.tsx | 7 +- sections/dashboard/Stake/StakingTab.tsx | 22 +- sections/dashboard/Stake/StakingTabs.tsx | 2 +- .../dashboard/Stake/TradingRewardsTab.tsx | 294 +++++++------ .../dashboard/Stake/VestConfirmationModal.tsx | 3 +- .../dashboard/Stake/{common.tsx => card.ts} | 0 .../SynthBalancesTable/SynthBalancesTable.tsx | 32 +- sections/dashboard/mobile.ts | 72 ++++ sections/earn/GridData.tsx | 2 +- sections/earn/StakeGrid.tsx | 18 +- sections/earn/StepOne.tsx | 4 +- sections/earn/StepTwo.tsx | 26 +- sections/earn/{common.tsx => grid.ts} | 18 +- sections/earn/text.ts | 18 + .../exchange/{BasicSwap => }/BasicSwap.tsx | 10 +- sections/exchange/BasicSwap/index.ts | 1 - .../{ExchangeContent => }/ExchangeContent.tsx | 0 sections/exchange/ExchangeContent/index.ts | 1 - .../{ExchangeHead => }/ExchangeHead.tsx | 0 sections/exchange/ExchangeHead/index.ts | 1 - .../{ExchangeModals => }/ExchangeModals.tsx | 0 sections/exchange/ExchangeModals/index.ts | 1 - .../ConnectWalletCard.tsx | 14 +- .../FooterCard/ConnectWalletCard/index.ts | 1 - .../MarketClosureCard.tsx | 14 +- .../FooterCard/MarketClosureCard/index.ts | 1 - .../SettleTransactionsCard.tsx | 13 +- .../SettleTransactionsCard/index.ts | 1 - .../TradeSummaryCard.tsx | 72 ++-- .../FooterCard/TradeSummaryCard/index.ts | 2 - sections/exchange/MobileSwap/SwapInfoBox.tsx | 10 +- .../{BasicSwap => }/SwapCurrencies.tsx | 0 .../TradeCard/CurrencyCard/CurrencyCard.tsx | 6 +- .../CurrencyCard/CurrencyCardInput.tsx | 3 +- .../CurrencyCard/CurrencyCardSelector.tsx | 3 +- .../CurrencyCard/MobileCurrencyCard.tsx | 3 +- .../{FooterCard/common.tsx => message.ts} | 22 +- .../common.tsx => exchange/summary.ts} | 14 + .../CrossMarginOnboard/CrossMarginOnboard.tsx | 4 +- sections/futures/FeeInfoBox/FeeInfoBox.tsx | 31 +- .../futures/LeverageInput/LeverageInput.tsx | 8 +- .../futures/LeverageSlider/LeverageSlider.tsx | 54 ++- .../futures/MarketDetails/MarketDetail.tsx | 16 +- .../futures/MarketDetails/MarketDetails.tsx | 2 +- sections/futures/MarketInfo/MarketHead.tsx | 10 +- .../futures/MarketInfoBox/MarketInfoBox.tsx | 22 +- .../MobileTrade/OverviewTabs/AccountTab.tsx | 3 +- .../MobileTrade/OverviewTabs/PriceTab.tsx | 3 +- .../MobileTrade/OverviewTabs/StatsTab.tsx | 3 +- .../MobileTrade/OverviewTabs/TradesTab.tsx | 3 +- .../futures/MobileTrade/PositionDetails.tsx | 2 +- .../MobileTrade/UserTabs/OrdersTab.tsx | 3 +- .../MobileTrade/UserTabs/TradesTab.tsx | 29 +- .../MobileTrade/UserTabs/TransfersTab.tsx | 33 +- .../MobileTrade/drawers/TradeDrawer.tsx | 2 +- .../OrderPriceInput/OrderPriceInput.tsx | 8 +- .../futures/OrderSizing/OrderSizeSlider.tsx | 5 +- sections/futures/OrderSizing/OrderSizing.tsx | 8 +- .../PositionButtons/PositionButtons.tsx | 8 +- .../PositionCard/ClosePositionModal.tsx | 7 +- .../futures/PositionCard/PositionCard.tsx | 103 ++--- .../futures/PositionChart/PositionChart.tsx | 4 +- .../futures/ShareModal/AmountContainer.tsx | 43 +- .../Trade/DelayedOrderConfirmationModal.tsx | 8 +- sections/futures/Trade/FuturesUnsupported.tsx | 10 +- sections/futures/Trade/ManagePosition.tsx | 12 +- .../futures/Trade/MarketsDropdownOption.tsx | 2 +- .../Trade/MarketsDropdownSingleValue.tsx | 2 +- .../futures/Trade/TradeConfirmationModal.tsx | 4 +- .../futures/Trade/TradeIsolatedMargin.tsx | 2 +- .../Trade/TransferIsolatedMarginModal.tsx | 4 +- .../TradeCrossMargin/CreateAccount.tsx | 2 +- .../TradeCrossMargin/CrossMarginInfoBox.tsx | 16 +- .../DepositWithdrawCrossMargin.tsx | 4 +- .../EditCrossMarginLeverageModal.tsx | 4 +- .../ManageKeeperBalanceModal.tsx | 2 +- sections/futures/Trades/TimeDisplay.tsx | 32 +- sections/futures/Trades/Trades.tsx | 40 +- sections/futures/TradingHistory/SkewInfo.tsx | 4 +- .../TradingHistory/TradesHistoryTable.tsx | 7 +- sections/futures/Transfers/Transfers.tsx | 25 +- sections/futures/UserInfo/OpenOrdersTable.tsx | 41 +- .../{MobileTrade/common.ts => mobile.ts} | 0 sections/homepage/{Assets => }/Assets.tsx | 100 ++--- sections/homepage/Assets/index.ts | 1 - sections/homepage/{Earning => }/Earning.tsx | 11 +- sections/homepage/Earning/index.ts | 1 - sections/homepage/{Features => }/Features.tsx | 10 +- sections/homepage/Features/index.ts | 1 - sections/homepage/{Hero => }/Hero.tsx | 13 +- sections/homepage/Hero/index.ts | 1 - .../homepage/{ShortList => }/ShortList.tsx | 23 +- sections/homepage/ShortList/index.ts | 1 - sections/homepage/{TradeNow => }/TradeNow.tsx | 6 +- sections/homepage/TradeNow/index.ts | 1 - .../containers/SmoothScroll/SmoothScroll.tsx | 27 -- .../containers/SmoothScroll/index.tsx | 1 - sections/homepage/containers/index.tsx | 13 - sections/homepage/{common.tsx => section.ts} | 18 +- sections/homepage/text.ts | 17 + .../leaderboard/{AllTime => }/AllTime.tsx | 23 +- sections/leaderboard/AllTime/index.tsx | 1 - .../{Competition => }/Competition.tsx | 37 +- .../leaderboard/Competition/constants.tsx | 5 - sections/leaderboard/Competition/index.tsx | 1 - .../{Leaderboard => }/Leaderboard.tsx | 43 +- sections/leaderboard/Leaderboard/index.tsx | 1 - sections/leaderboard/TraderHistory.tsx | 368 +++++++++++++++++ .../TraderHistory/TraderHistory.tsx | 390 ------------------ sections/leaderboard/TraderHistory/index.tsx | 1 - sections/leaderboard/common.tsx | 34 -- sections/leaderboard/medal.ts | 6 + sections/leaderboard/trader.ts | 11 + .../shared/Layout/AppLayout/AppLayout.tsx | 6 +- .../AppLayout/{GitHashID => }/GitHashID.tsx | 0 .../Layout/AppLayout/GitHashID/index.ts | 1 - .../AppLayout/Header/BalanceActions.tsx | 119 +++--- .../Layout/AppLayout/Header/ConnectionDot.tsx | 1 + .../Header/MobileUserMenu/MobileMenuModal.tsx | 2 +- .../MobileUserMenu/MobileSettingsModal.tsx | 2 +- .../Header/MobileUserMenu/MobileSubMenu.tsx | 120 +++--- .../Header/MobileUserMenu/MobileUserMenu.tsx | 8 +- .../MobileUserMenu/MobileWalletActions.tsx | 6 +- .../MobileUserMenu/MobileWalletButton.tsx | 37 +- .../MobileUserMenu/{common.ts => menu.ts} | 19 - .../Layout/AppLayout/Header/{Nav => }/Nav.tsx | 38 +- .../Layout/AppLayout/Header/Nav/index.ts | 1 - .../AppLayout/Header/NetworksSwitcher.tsx | 6 +- .../Layout/AppLayout/Header/WalletActions.tsx | 13 +- .../Layout/AppLayout/Header/WalletButtons.tsx | 8 +- .../shared/Layout/HomeLayout/Background.tsx | 7 +- sections/shared/Layout/HomeLayout/Banner.tsx | 19 +- sections/shared/Layout/HomeLayout/Footer.tsx | 13 +- sections/shared/Layout/HomeLayout/Header.tsx | 10 +- .../shared/Layout/HomeLayout/HomeLayout.tsx | 2 +- sections/shared/Layout/{Logo => }/Logo.tsx | 10 +- sections/shared/Layout/Logo/index.ts | 1 - .../{SystemStatus => }/SystemStatus.tsx | 10 +- sections/shared/SystemStatus/index.ts | 1 - .../CompetitionBanner.tsx | 30 +- .../components/CompetitionBanner/index.ts | 1 - .../CompetitionState.tsx | 1 - .../{FeeCostSummary => }/FeeCostSummary.tsx | 3 +- .../shared/components/FeeCostSummary/index.ts | 1 - .../{FeeRateSummary => }/FeeRateSummary.tsx | 43 +- .../shared/components/FeeRateSummary/index.ts | 1 - .../{GasPriceSelect => }/GasPriceSelect.tsx | 45 +- .../shared/components/GasPriceSelect/index.ts | 1 - .../PriceCurrencySelect.tsx | 45 -- .../PriceImpactSummary.tsx | 5 +- .../components/PriceImpactSummary/index.ts | 1 - .../SlippageSelect/SlippageSelect.tsx | 152 ------- .../{SelectCurrencyModal => }/CurrencyRow.tsx | 0 .../SelectCurrencyModal.tsx | 4 +- .../modals/SelectCurrencyModal/index.ts | 1 - .../{TxApproveModal => }/TxApproveModal.tsx | 5 +- .../shared/modals/TxApproveModal/index.ts | 1 - .../TxConfirmationModal.tsx | 20 +- .../modals/TxConfirmationModal/index.ts | 1 - .../{TxSettleModal => }/TxSettleModal.tsx | 5 +- sections/shared/modals/TxSettleModal/index.ts | 1 - sections/stats/stats.styles.tsx | 2 +- state/futures/selectors.ts | 8 + store/utils.ts | 3 - store/wallet/index.ts | 21 +- stories/Tooltip.stories.tsx | 8 +- styles/common.tsx | 66 +-- styles/theme/colors/index.ts | 4 - testing/unit/mocks/MockProviders.tsx | 6 +- utils/competition.tsx | 18 + utils/futures.ts | 2 +- 253 files changed, 2296 insertions(+), 2928 deletions(-) delete mode 100644 components/Currency/common.tsx delete mode 100644 components/Error/index.ts rename components/{Error/Error.tsx => ErrorView/ErrorView.tsx} (59%) create mode 100644 components/ErrorView/index.ts delete mode 100644 components/ProgressBar/ProgressBar.tsx delete mode 100644 components/ProgressBar/index.ts create mode 100644 components/README.md rename components/Tooltip/{TooltipStyles.tsx => BaseTooltip.tsx} (95%) rename components/Tooltip/{StyledTooltip.tsx => Tooltip.tsx} (70%) create mode 100644 components/layout/flex.ts create mode 100644 components/layout/grid.ts rename sections/shared/modals/common.tsx => components/layout/modals.ts (91%) create mode 100644 constants/menu.ts delete mode 100644 containers/index.tsx delete mode 100644 sections/dashboard/FuturesPositionsTable/constants.ts delete mode 100644 sections/dashboard/MobileDashboard/common.ts rename sections/dashboard/Stake/{common.tsx => card.ts} (100%) create mode 100644 sections/dashboard/mobile.ts rename sections/earn/{common.tsx => grid.ts} (62%) create mode 100644 sections/earn/text.ts rename sections/exchange/{BasicSwap => }/BasicSwap.tsx (78%) delete mode 100644 sections/exchange/BasicSwap/index.ts rename sections/exchange/{ExchangeContent => }/ExchangeContent.tsx (100%) delete mode 100644 sections/exchange/ExchangeContent/index.ts rename sections/exchange/{ExchangeHead => }/ExchangeHead.tsx (100%) delete mode 100644 sections/exchange/ExchangeHead/index.ts rename sections/exchange/{ExchangeModals => }/ExchangeModals.tsx (100%) delete mode 100644 sections/exchange/ExchangeModals/index.ts rename sections/exchange/FooterCard/{ConnectWalletCard => }/ConnectWalletCard.tsx (77%) delete mode 100644 sections/exchange/FooterCard/ConnectWalletCard/index.ts rename sections/exchange/FooterCard/{MarketClosureCard => }/MarketClosureCard.tsx (88%) delete mode 100644 sections/exchange/FooterCard/MarketClosureCard/index.ts rename sections/exchange/FooterCard/{SettleTransactionsCard => }/SettleTransactionsCard.tsx (92%) delete mode 100644 sections/exchange/FooterCard/SettleTransactionsCard/index.ts rename sections/exchange/FooterCard/{TradeSummaryCard => }/TradeSummaryCard.tsx (77%) delete mode 100644 sections/exchange/FooterCard/TradeSummaryCard/index.ts rename sections/exchange/{BasicSwap => }/SwapCurrencies.tsx (100%) rename sections/exchange/{FooterCard/common.tsx => message.ts} (63%) rename sections/{shared/components/common.tsx => exchange/summary.ts} (70%) rename sections/futures/{MobileTrade/common.ts => mobile.ts} (100%) rename sections/homepage/{Assets => }/Assets.tsx (90%) delete mode 100644 sections/homepage/Assets/index.ts rename sections/homepage/{Earning => }/Earning.tsx (93%) delete mode 100644 sections/homepage/Earning/index.ts rename sections/homepage/{Features => }/Features.tsx (97%) delete mode 100644 sections/homepage/Features/index.ts rename sections/homepage/{Hero => }/Hero.tsx (88%) delete mode 100644 sections/homepage/Hero/index.ts rename sections/homepage/{ShortList => }/ShortList.tsx (95%) delete mode 100644 sections/homepage/ShortList/index.ts rename sections/homepage/{TradeNow => }/TradeNow.tsx (92%) delete mode 100644 sections/homepage/TradeNow/index.ts delete mode 100644 sections/homepage/containers/SmoothScroll/SmoothScroll.tsx delete mode 100644 sections/homepage/containers/SmoothScroll/index.tsx delete mode 100644 sections/homepage/containers/index.tsx rename sections/homepage/{common.tsx => section.ts} (50%) create mode 100644 sections/homepage/text.ts rename sections/leaderboard/{AllTime => }/AllTime.tsx (93%) delete mode 100644 sections/leaderboard/AllTime/index.tsx rename sections/leaderboard/{Competition => }/Competition.tsx (92%) delete mode 100644 sections/leaderboard/Competition/constants.tsx delete mode 100644 sections/leaderboard/Competition/index.tsx rename sections/leaderboard/{Leaderboard => }/Leaderboard.tsx (87%) delete mode 100644 sections/leaderboard/Leaderboard/index.tsx create mode 100644 sections/leaderboard/TraderHistory.tsx delete mode 100644 sections/leaderboard/TraderHistory/TraderHistory.tsx delete mode 100644 sections/leaderboard/TraderHistory/index.tsx delete mode 100644 sections/leaderboard/common.tsx create mode 100644 sections/leaderboard/medal.ts create mode 100644 sections/leaderboard/trader.ts rename sections/shared/Layout/AppLayout/{GitHashID => }/GitHashID.tsx (100%) delete mode 100644 sections/shared/Layout/AppLayout/GitHashID/index.ts rename sections/shared/Layout/AppLayout/Header/MobileUserMenu/{common.ts => menu.ts} (62%) rename sections/shared/Layout/AppLayout/Header/{Nav => }/Nav.tsx (86%) delete mode 100644 sections/shared/Layout/AppLayout/Header/Nav/index.ts rename sections/shared/Layout/{Logo => }/Logo.tsx (88%) delete mode 100644 sections/shared/Layout/Logo/index.ts rename sections/shared/{SystemStatus => }/SystemStatus.tsx (94%) delete mode 100644 sections/shared/SystemStatus/index.ts rename sections/shared/components/{CompetitionBanner => }/CompetitionBanner.tsx (77%) delete mode 100644 sections/shared/components/CompetitionBanner/index.ts rename sections/shared/components/{CompetitionBanner => }/CompetitionState.tsx (98%) rename sections/shared/components/{FeeCostSummary => }/FeeCostSummary.tsx (96%) delete mode 100644 sections/shared/components/FeeCostSummary/index.ts rename sections/shared/components/{FeeRateSummary => }/FeeRateSummary.tsx (72%) delete mode 100644 sections/shared/components/FeeRateSummary/index.ts rename sections/shared/components/{GasPriceSelect => }/GasPriceSelect.tsx (72%) delete mode 100644 sections/shared/components/GasPriceSelect/index.ts delete mode 100644 sections/shared/components/PriceCurrencySelect/PriceCurrencySelect.tsx rename sections/shared/components/{PriceImpactSummary => }/PriceImpactSummary.tsx (86%) delete mode 100644 sections/shared/components/PriceImpactSummary/index.ts delete mode 100644 sections/shared/components/SlippageSelect/SlippageSelect.tsx rename sections/shared/modals/{SelectCurrencyModal => }/CurrencyRow.tsx (100%) rename sections/shared/modals/{SelectCurrencyModal => }/SelectCurrencyModal.tsx (98%) delete mode 100644 sections/shared/modals/SelectCurrencyModal/index.ts rename sections/shared/modals/{TxApproveModal => }/TxApproveModal.tsx (93%) delete mode 100644 sections/shared/modals/TxApproveModal/index.ts rename sections/shared/modals/{TxConfirmationModal => }/TxConfirmationModal.tsx (95%) delete mode 100644 sections/shared/modals/TxConfirmationModal/index.ts rename sections/shared/modals/{TxSettleModal => }/TxSettleModal.tsx (93%) delete mode 100644 sections/shared/modals/TxSettleModal/index.ts create mode 100644 utils/competition.tsx diff --git a/components/Badge/MarketBadge.tsx b/components/Badge/MarketBadge.tsx index bf12b93cb8..ee83e69fbe 100644 --- a/components/Badge/MarketBadge.tsx +++ b/components/Badge/MarketBadge.tsx @@ -1,4 +1,4 @@ -import React, { FC } from 'react'; +import React, { FC, memo } from 'react'; import { useTranslation } from 'react-i18next'; import styled from 'styled-components'; @@ -20,45 +20,43 @@ type TransitionBadgeProps = { isOpen: boolean; }; -export const TransitionBadge: FC = ({ isOpen }) => { +export const TransitionBadge: FC = memo(({ isOpen }) => { const { t } = useTranslation(); return ( - {t(`futures.market.state.${isOpen ? 'closes-soon' : 'opens-soon'}`)} + {t(`futures.market.state.${isOpen ? 'closes' : 'opens'}-soon`)} ); -}; +}); -export const MarketBadge: FC = ({ - currencyKey, - isFuturesMarketClosed, - futuresClosureReason, -}) => { - const { t } = useTranslation(); - const isOpen = marketIsOpen((currencyKey as CurrencyKey) ?? null); +export const MarketBadge: FC = memo( + ({ currencyKey, isFuturesMarketClosed, futuresClosureReason }) => { + const { t } = useTranslation(); + const isOpen = marketIsOpen((currencyKey as CurrencyKey) ?? null); - const nextOpen = marketNextOpen((currencyKey as CurrencyKey) ?? ''); - const nextTransition = marketNextTransition((currencyKey as CurrencyKey) ?? ''); + const nextOpen = marketNextOpen((currencyKey as CurrencyKey) ?? ''); + const nextTransition = marketNextTransition((currencyKey as CurrencyKey) ?? ''); - const timerSetting = isOpen === null ? null : isOpen ? nextTransition : nextOpen; - const isMarketTransitioning = useIsMarketTransitioning(timerSetting ?? null); + const timerSetting = isOpen === null ? null : isOpen ? nextTransition : nextOpen; + const isMarketTransitioning = useIsMarketTransitioning(timerSetting ?? null); - if (typeof isFuturesMarketClosed !== 'boolean') { - return null; - } + if (typeof isFuturesMarketClosed !== 'boolean') { + return null; + } - if (isFuturesMarketClosed) { - const reason = futuresClosureReason || 'unknown'; - return {t(`futures.market.state.${reason}`)}; - } + if (isFuturesMarketClosed) { + const reason = futuresClosureReason || 'unknown'; + return {t(`futures.market.state.${reason}`)}; + } - if (isMarketTransitioning && isOpen !== null) { - return ; - } + if (isMarketTransitioning && isOpen !== null) { + return ; + } - return null; -}; + return null; + } +); export default MarketBadge; diff --git a/components/BaseModal/BaseModal.tsx b/components/BaseModal/BaseModal.tsx index e661eb1693..ed13b49587 100644 --- a/components/BaseModal/BaseModal.tsx +++ b/components/BaseModal/BaseModal.tsx @@ -1,10 +1,10 @@ import { DialogOverlay, DialogContent } from '@reach/dialog'; -import { FC, ReactNode } from 'react'; +import { FC, memo, ReactNode } from 'react'; import { Rnd, Props } from 'react-rnd'; import styled from 'styled-components'; import CrossIcon from 'assets/svg/app/cross.svg'; -import Card from 'components/Card'; +import Card, { CardHeader, CardBody } from 'components/Card'; import { zIndex } from 'constants/ui'; import { resetButtonCSS } from 'styles/common'; import media from 'styles/media'; @@ -19,32 +19,32 @@ type BaseModalProps = { rndProps?: Props; }; -export const BaseModal: FC = ({ - onDismiss, - title, - children, - isOpen, - showCross = true, - lowercase, - rndProps = { disableDragging: true, enableResizing: false }, - ...rest -}) => ( - - - {rndProps.disableDragging ? ( - - - {title} - {showCross && ( - - - - )} - - {children} - - ) : ( - +type ModalContentWrapperProps = { + rndProps?: Props; +}; + +const ModalContentWrapper: FC = memo(({ children, rndProps }) => { + if (rndProps?.disableDragging) { + return <>{children}; + } else { + return {children}; + } +}); + +export const BaseModal: FC = memo( + ({ + onDismiss, + title, + children, + isOpen, + showCross = true, + lowercase, + rndProps = { disableDragging: true, enableResizing: false }, + ...rest + }) => ( + + + {title} @@ -56,10 +56,10 @@ export const BaseModal: FC = ({ {children} - - )} - - + + + + ) ); const StyledDialogOverlay = styled(DialogOverlay)` @@ -100,14 +100,14 @@ const StyledCard = styled(Card)` `} `; -const StyledCardHeader = styled(Card.Header)` +const StyledCardHeader = styled(CardHeader)` height: 45px; font-size: 16px; font-family: ${(props) => props.theme.fonts.regular}; padding: 20px; `; -const StyledCardBody = styled(Card.Body)` +const StyledCardBody = styled(CardBody)` overflow-y: scroll; padding: 0 20px; padding-bottom: 20px; diff --git a/components/Button/TabButton.tsx b/components/Button/TabButton.tsx index b4dbc6d4a0..d73b8a5096 100644 --- a/components/Button/TabButton.tsx +++ b/components/Button/TabButton.tsx @@ -19,8 +19,8 @@ export type TabButtonProps = { }; const TabButton: React.FC = React.memo( - ({ title, detail, badge, active, icon, vertical, titleIcon, nofill, ...props }) => ( - + ({ title, detail, badge, icon, titleIcon, ...props }) => ( + {!!icon &&
{icon}
}
diff --git a/components/Card/Card.tsx b/components/Card/Card.tsx index e1c1ba3b81..6078180d66 100644 --- a/components/Card/Card.tsx +++ b/components/Card/Card.tsx @@ -1,30 +1,18 @@ import { FC, memo } from 'react'; import styled from 'styled-components'; -import CardBody, { CardBodyProps } from './CardBody'; -import CardHeader, { CardHeaderProps } from './CardHeader'; - type CardProps = { children: React.ReactNode; isRounded?: boolean; className?: string; }; -interface StaticComponents { - Header: FC; - Body: FC; -} - -// @ts-ignore -const Card: FC & StaticComponents = memo(({ children, isRounded, ...rest }) => ( +const Card: FC = memo(({ children, isRounded, ...rest }) => ( {children} )); -Card.Header = CardHeader; -Card.Body = CardBody; - const Container = styled.div<{ isRounded?: boolean }>` display: flex; flex-direction: column; diff --git a/components/Card/CardBody.tsx b/components/Card/CardBody.tsx index 1b14512c56..0b869938c8 100644 --- a/components/Card/CardBody.tsx +++ b/components/Card/CardBody.tsx @@ -1,7 +1,7 @@ import { FC, memo } from 'react'; import styled from 'styled-components'; -import { FlexDivCol } from 'styles/common'; +import { FlexDivCol } from 'components/layout/flex'; export type CardBodyProps = { children: React.ReactNode; diff --git a/components/Card/CardHeader.tsx b/components/Card/CardHeader.tsx index b4b6d53346..2c56526372 100644 --- a/components/Card/CardHeader.tsx +++ b/components/Card/CardHeader.tsx @@ -1,7 +1,7 @@ import React, { FC, memo } from 'react'; import styled from 'styled-components'; -import { FlexDivCentered } from 'styles/common'; +import { FlexDivCentered } from 'components/layout/flex'; export type CardHeaderProps = { children: React.ReactNode; @@ -21,7 +21,7 @@ const CardHeader: FC = memo( const Container = styled(FlexDivCentered)<{ lowercase: boolean; noBorder: boolean }>` position: relative; color: ${(props) => props.theme.colors.selectedTheme.button.text.primary}; - border-bottom: ${(props) => (props.noBorder ? 'none' : `1px solid ${props.theme.colors.navy}`)}; + border-bottom: ${(props) => (props.noBorder ? 'none' : props.theme.colors.selectedTheme.border)}; height: 32px; padding: 0 18px; justify-content: flex-start; diff --git a/components/Card/index.ts b/components/Card/index.ts index c68311df80..cf56eb9b32 100644 --- a/components/Card/index.ts +++ b/components/Card/index.ts @@ -1 +1,3 @@ export { default } from './Card'; +export { default as CardHeader } from './CardHeader'; +export { default as CardBody } from './CardBody'; diff --git a/components/ChangePercent/ChangePercent.tsx b/components/ChangePercent/ChangePercent.tsx index 272f7797f4..75fbaa0208 100644 --- a/components/ChangePercent/ChangePercent.tsx +++ b/components/ChangePercent/ChangePercent.tsx @@ -1,5 +1,5 @@ import { wei, WeiSource } from '@synthetixio/wei'; -import { FC } from 'react'; +import { FC, memo } from 'react'; import styled from 'styled-components'; import ChangeNegativeIcon from 'assets/svg/app/change-negative.svg'; @@ -14,31 +14,28 @@ type ChangePercentProps = { showArrow?: boolean; }; -export const ChangePercent: FC = ({ - value, - decimals = 2, - showArrow = true, - ...rest -}) => { - const isValid = !!value; - const isZero = value && wei(value).eq(0); - const isPositive = value && wei(value).gt(0); +export const ChangePercent: FC = memo( + ({ value, decimals = 2, showArrow = true, ...rest }) => { + const isValid = !!value; + const isZero = value && wei(value).eq(0); + const isPositive = value && wei(value).gt(0); - return ( - - {!isValid ? ( - <>{NO_VALUE} - ) : !showArrow ? ( - <> - ) : !isZero && isPositive ? ( - - ) : ( - - )} - {value && formatPercent(wei(value).abs(), { minDecimals: decimals })} - - ); -}; + return ( + + {!isValid ? ( + <>{NO_VALUE} + ) : !showArrow ? ( + <> + ) : !isZero && isPositive ? ( + + ) : ( + + )} + {value && formatPercent(wei(value).abs(), { minDecimals: decimals })} + + ); + } +); const CurrencyChange = styled.span<{ isValid: boolean; isPositive: boolean }>` display: inline-flex; diff --git a/components/Checkbox/Checkbox.tsx b/components/Checkbox/Checkbox.tsx index de590c706f..c367c0f649 100644 --- a/components/Checkbox/Checkbox.tsx +++ b/components/Checkbox/Checkbox.tsx @@ -1,22 +1,19 @@ +import { FC, memo } from 'react'; import styled from 'styled-components'; -export const Checkbox = ({ - id, - label, - checked, - onChange, - ...props -}: { +type CheckboxProps = { id: string; label: string; checked: boolean; onChange: () => void; -}) => ( +}; + +export const Checkbox: FC = memo(({ id, label, checked, onChange, ...props }) => ( -); +)); const CheckboxContainer = styled.div` color: ${(props) => props.theme.colors.selectedTheme.gray}; diff --git a/components/Currency/CurrencyAmount/CurrencyAmount.tsx b/components/Currency/CurrencyAmount/CurrencyAmount.tsx index 9ea92af667..cdf0298377 100644 --- a/components/Currency/CurrencyAmount/CurrencyAmount.tsx +++ b/components/Currency/CurrencyAmount/CurrencyAmount.tsx @@ -1,12 +1,11 @@ import Wei, { wei } from '@synthetixio/wei'; import { ethers } from 'ethers'; -import React, { FC } from 'react'; +import { FC, memo } from 'react'; import styled from 'styled-components'; +import { ContainerRowMixin } from 'components/layout/grid'; import { formatCurrency, FormatCurrencyOptions } from 'utils/formatters/number'; -import { ContainerRowMixin } from '../common'; - type WeiSource = Wei | number | string | ethers.BigNumber; type CurrencyAmountProps = { @@ -21,32 +20,36 @@ type CurrencyAmountProps = { showValue?: boolean; }; -export const CurrencyAmount: FC = ({ - currencyKey, - amount, - totalValue, - sign, - conversionRate, - formatAmountOptions = {}, - formatTotalValueOptions = {}, - showTotalValue = true, - showValue = true, - ...rest -}) => ( - - {!showValue ? null : ( - {formatCurrency(currencyKey, amount, formatAmountOptions)} - )} - {!showTotalValue ? null : ( - - {formatCurrency( - currencyKey, - conversionRate != null ? wei(totalValue).div(conversionRate) : totalValue, - { sign, ...formatTotalValueOptions } - )} - - )} - +export const CurrencyAmount: FC = memo( + ({ + currencyKey, + amount, + totalValue, + sign, + conversionRate, + formatAmountOptions = {}, + formatTotalValueOptions = {}, + showTotalValue = true, + showValue = true, + ...rest + }) => ( + + {!showValue ? null : ( + + {formatCurrency(currencyKey, amount, formatAmountOptions)} + + )} + {!showTotalValue ? null : ( + + {formatCurrency( + currencyKey, + conversionRate != null ? wei(totalValue).div(conversionRate) : totalValue, + { sign, ...formatTotalValueOptions } + )} + + )} + + ) ); const Container = styled.span` diff --git a/components/Currency/CurrencyIcon/TokenIcon.tsx b/components/Currency/CurrencyIcon/TokenIcon.tsx index 6b28ab1087..458d49b770 100644 --- a/components/Currency/CurrencyIcon/TokenIcon.tsx +++ b/components/Currency/CurrencyIcon/TokenIcon.tsx @@ -1,8 +1,8 @@ -import { FC } from 'react'; +import { FC, memo } from 'react'; import styled from 'styled-components'; +import { FlexDivCentered } from 'components/layout/flex'; import { useAppSelector } from 'state/hooks'; -import { FlexDivCentered } from 'styles/common'; export type TokenIconProps = { currencyKey: string; @@ -15,7 +15,7 @@ export type TokenIconProps = { url?: string; }; -const TokenIcon: FC = ({ currencyKey, isDeprecated, ...props }) => { +const TokenIcon: FC = memo(({ currencyKey, isDeprecated, ...props }) => { const tokensMap = useAppSelector(({ exchange }) => exchange.tokensMap); if (!!tokensMap[currencyKey]) { @@ -29,7 +29,7 @@ const TokenIcon: FC = ({ currencyKey, isDeprecated, ...props }) ); } -}; +}); const TokenImage = styled.img<{ $isDeprecated?: boolean }>` border-radius: 100%; diff --git a/components/Currency/CurrencyName/CurrencyName.tsx b/components/Currency/CurrencyName/CurrencyName.tsx index e615a3f8db..122a322b63 100644 --- a/components/Currency/CurrencyName/CurrencyName.tsx +++ b/components/Currency/CurrencyName/CurrencyName.tsx @@ -1,11 +1,11 @@ -import React, { FC } from 'react'; +import React, { memo, FC } from 'react'; import { useTranslation } from 'react-i18next'; import styled, { css } from 'styled-components'; +import { ContainerRowMixin } from 'components/layout/grid'; import MarketClosureIcon from 'components/MarketClosureIcon'; import { MarketClosureReason } from 'hooks/useMarketClosed'; -import { ContainerRowMixin } from '../common'; import CurrencyIcon from '../CurrencyIcon'; import { CurrencyIconProps } from '../CurrencyIcon/CurrencyIcon'; @@ -19,43 +19,45 @@ type CurrencyNameProps = { isDeprecated?: boolean; }; -export const CurrencyName: FC = ({ - currencyKey, - symbol, - name = null, - showIcon = false, - iconProps = {}, - marketClosureReason, - isDeprecated = false, - ...rest -}) => { - const { t } = useTranslation(); - return ( - - {showIcon && ( - - - {marketClosureReason != null ? ( - - - - ) : null} - - )} - - - {symbol || currencyKey} - {!isDeprecated ? null : ( - - {t('common.currency.deprecated')} - - )} - - {name && {name}} - - - ); -}; +export const CurrencyName: FC = memo( + ({ + currencyKey, + symbol, + name = null, + showIcon = false, + iconProps = {}, + marketClosureReason, + isDeprecated = false, + ...rest + }) => { + const { t } = useTranslation(); + return ( + + {showIcon && ( + + + {marketClosureReason != null ? ( + + + + ) : null} + + )} + + + {symbol || currencyKey} + {!isDeprecated ? null : ( + + {t('common.currency.deprecated')} + + )} + + {name && {name}} + + + ); + } +); const Container = styled.span<{ showIcon?: boolean }>` ${(props) => diff --git a/components/Currency/CurrencyPrice/CurrencyPrice.tsx b/components/Currency/CurrencyPrice/CurrencyPrice.tsx index 49daa658aa..896b88e0f6 100644 --- a/components/Currency/CurrencyPrice/CurrencyPrice.tsx +++ b/components/Currency/CurrencyPrice/CurrencyPrice.tsx @@ -1,14 +1,13 @@ import Wei, { wei } from '@synthetixio/wei'; import { ethers } from 'ethers'; -import React, { FC, useMemo } from 'react'; +import React, { FC, memo } from 'react'; import styled from 'styled-components'; import ChangePercent from 'components/ChangePercent'; +import { ContainerRowMixin } from 'components/layout/grid'; import { CurrencyKey } from 'constants/currency'; import { formatCurrency, FormatCurrencyOptions } from 'utils/formatters/number'; -import { ContainerRowMixin } from '../common'; - type WeiSource = Wei | number | string | ethers.BigNumber; type CurrencyPriceProps = { @@ -22,55 +21,43 @@ type CurrencyPriceProps = { truncate?: boolean; }; -export const CurrencyPrice: FC = ({ - currencyKey, - price, - sign, - change, - conversionRate, - showCurrencyKey, - formatOptions, - truncate = false, - ...rest -}) => { - const cleanPrice = useMemo(() => { - try { - return wei(price); - } catch { - return ''; - } - }, [price]); +export const CurrencyPrice: FC = memo( + ({ + currencyKey, + price, + sign, + change, + conversionRate, + showCurrencyKey, + formatOptions, + truncate = false, + ...rest + }) => { + const cleanPrice = wei(price); + const cleanConversionRate = wei(conversionRate ?? 0); - const cleanConversionRate = useMemo(() => { - try { - return wei(conversionRate); - } catch { - return ''; + if (truncate && price > 1e6) { + formatOptions = { ...formatOptions, truncation: { divisor: 1e6, unit: 'M' } }; } - }, [conversionRate]); - if (truncate && price > 1e6) { - formatOptions = { ...formatOptions, truncation: { divisor: 1e6, unit: 'M' } }; + return ( + + + {formatCurrency( + currencyKey, + cleanConversionRate.gt(0) ? cleanPrice.div(cleanConversionRate) : cleanPrice, + { + sign, + currencyKey: showCurrencyKey ? currencyKey : undefined, + ...formatOptions, + } + )} + + {!!change && } + + ); } - return ( - - - {formatCurrency( - currencyKey, - cleanConversionRate && cleanPrice && cleanConversionRate.gt(0) - ? cleanPrice.div(cleanConversionRate) - : cleanPrice, - { - sign, - currencyKey: showCurrencyKey != null ? currencyKey : undefined, - ...formatOptions, - } - )} - - {change != null && } - - ); -}; +); const Container = styled.span` ${ContainerRowMixin}; diff --git a/components/Currency/common.tsx b/components/Currency/common.tsx deleted file mode 100644 index fcfd55f1fa..0000000000 --- a/components/Currency/common.tsx +++ /dev/null @@ -1,4 +0,0 @@ -export const ContainerRowMixin = ` - display: inline-grid; - grid-gap: 1px; -`; diff --git a/components/Error/index.ts b/components/Error/index.ts deleted file mode 100644 index 3edca40045..0000000000 --- a/components/Error/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './Error'; diff --git a/components/Error/Error.tsx b/components/ErrorView/ErrorView.tsx similarity index 59% rename from components/Error/Error.tsx rename to components/ErrorView/ErrorView.tsx index 9fc5137193..ca63c5b710 100644 --- a/components/Error/Error.tsx +++ b/components/ErrorView/ErrorView.tsx @@ -1,4 +1,4 @@ -import React, { FC, useMemo } from 'react'; +import React, { FC, useMemo, memo } from 'react'; import { useTranslation } from 'react-i18next'; import styled from 'styled-components'; @@ -24,40 +24,36 @@ export const FRIENDLY_I18N_MESSAGES: Record = { 'Insufficient margin': 'futures.market.errors.insufficient-margin', }; -export const Error: FC = ({ - message, - formatter, - retryButton, - containerStyle, - messageType = 'error', -}) => { - const { t } = useTranslation(); - const formattedMessage = useMemo(() => { - if (FRIENDLY_I18N_MESSAGES[message]) return t(FRIENDLY_I18N_MESSAGES[message]); - switch (formatter) { - case 'revert': - return formatRevert(message); - default: - return message; - } - }, [message, formatter, t]); +export const ErrorView: FC = memo( + ({ message, formatter, retryButton, containerStyle, messageType = 'error' }) => { + const { t } = useTranslation(); + const formattedMessage = useMemo(() => { + if (FRIENDLY_I18N_MESSAGES[message]) return t(FRIENDLY_I18N_MESSAGES[message]); + switch (formatter) { + case 'revert': + return formatRevert(message); + default: + return message; + } + }, [message, formatter, t]); - if (isUserDeniedError(message) || !message) return null; + if (isUserDeniedError(message) || !message) return null; - return ( - -
{truncateString(formattedMessage)}
- {retryButton && ( - <> - - - - )} -
- ); -}; + return ( + +
{truncateString(formattedMessage)}
+ {retryButton && ( + <> + + + + )} +
+ ); + } +); const ErrorContainer = styled.div<{ messageType: MessageType; style: Record }>` color: ${(props) => @@ -84,4 +80,4 @@ const ErrorContainer = styled.div<{ messageType: MessageType; style: Record | undefined) => void; }; -export const FullScreenModal: FC = ({ - title, - children, - isOpen, - onDismiss, - ...rest -}) => ( - - - {title && {title}} -
{children}
-
-
+export const FullScreenModal: FC = memo( + ({ title, children, isOpen, onDismiss, ...rest }) => ( + + + {title && {title}} +
{children}
+
+
+ ) ); const StyledDialogOverlay = styled(DialogOverlay)` diff --git a/components/InfoBox/InfoBox.tsx b/components/InfoBox/InfoBox.tsx index 408f672bd3..9698800a34 100644 --- a/components/InfoBox/InfoBox.tsx +++ b/components/InfoBox/InfoBox.tsx @@ -1,6 +1,7 @@ -import React, { memo } from 'react'; -import styled from 'styled-components'; +import { memo, FC } from 'react'; +import styled, { css } from 'styled-components'; +import * as Text from 'components/Text'; import { NO_VALUE } from 'constants/placeholder'; export type DetailedInfo = { @@ -20,40 +21,49 @@ type InfoBoxProps = { dataTestId?: string; }; -const InfoBox: React.FC = memo( - ({ details, style, className, disabled, dataTestId }) => ( - - {Object.entries(details).map(([key, value], index) => { - if (value) { - return ( - - {value.compactBox ? ( - <>{value.keyNode} - ) : ( -
-
- {key}: {value.keyNode} -
-

- {disabled ? NO_VALUE : value.value} - {value.valueNode} -

-
- )} - {value?.spaceBeneath &&
} -
- ); - } - return null; - })} -
- ) -); +const InfoBox: FC = memo(({ details, disabled, dataTestId, ...props }) => ( + + {Object.entries(details).map(([key, value], index) => ( + + ))} + +)); + +type InfoBoxValueProps = { + title: string; + value?: DetailedInfo | null; + disabled?: boolean; + dataTestId: string; +}; + +const InfoBoxValue: FC = memo(({ title, value, disabled, dataTestId }) => { + if (!value) return null; + + return ( + <> + {value.compactBox ? ( + value.keyNode + ) : ( +
+ + {title}: {value.keyNode} + + + {disabled ? NO_VALUE : value.value} + {value.valueNode} + +
+ )} + {value?.spaceBeneath &&
} + + ); +}); const InfoBoxContainer = styled.div` border: ${(props) => props.theme.colors.selectedTheme.border}; @@ -67,51 +77,48 @@ const InfoBoxContainer = styled.div` justify-content: space-between; align-items: center; - p { - margin: 0; + &:not(:last-of-type) { + margin-bottom: 8px; } + } +`; - .key { - color: ${(props) => props.theme.colors.selectedTheme.text.title}; - font-size: 13px; - text-transform: capitalize; - cursor: default; - } +const InfoBoxKey = styled(Text.Body)` + color: ${(props) => props.theme.colors.selectedTheme.text.title}; + font-size: 13px; + text-transform: capitalize; + cursor: default; +`; - .value { - color: ${(props) => props.theme.colors.selectedTheme.text.value}; - font-family: ${(props) => props.theme.fonts.mono}; - font-size: 13px; - cursor: default; - } +const ValueText = styled(Text.Body)<{ $disabled?: boolean; $color?: DetailedInfo['color'] }>` + color: ${(props) => props.theme.colors.selectedTheme.text.value}; + font-family: ${(props) => props.theme.fonts.mono}; + font-size: 13px; + cursor: default; - .key { - color: ${(props) => props.theme.colors.selectedTheme.text.title}; - font-size: 13px; - text-transform: capitalize; - cursor: default; - } - - .red { + ${(props) => + props.$color === 'red' && + css` color: ${(props) => props.theme.colors.selectedTheme.red}; - } + `} - .green { + ${(props) => + props.$color === 'green' && + css` color: ${(props) => props.theme.colors.selectedTheme.green}; - } + `} - .gold { + ${(props) => + props.$color === 'gold' && + css` color: ${(props) => props.theme.colors.common.primaryGold}; - } + `} - .closed { + ${(props) => + props.$disabled && + css` color: ${(props) => props.theme.colors.selectedTheme.gray}; - } - - &:not(:last-of-type) { - margin-bottom: 8px; - } - } + `} `; export default InfoBox; diff --git a/components/Input/CustomInput.tsx b/components/Input/CustomInput.tsx index eb00df6d89..9eecc3daaa 100644 --- a/components/Input/CustomInput.tsx +++ b/components/Input/CustomInput.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import { memo, FC, useCallback } from 'react'; import styled from 'styled-components'; type CustomInputProps = { @@ -19,53 +19,51 @@ type CustomInputProps = { const INVALID_CHARS = ['-', '+', 'e']; -const CustomInput: React.FC = ({ - value, - placeholder, - onChange, - right, - left, - style, - className, - disabled, - id, - defaultValue, - dataTestId, - invalid, - textAlign = 'left', -}) => { - const handleChange = (e: React.ChangeEvent) => { - onChange(e, e.target.value.replace(/,/g, '.').replace(/[e+-]/gi, '')); - }; +const CustomInput: FC = memo( + ({ + value, + placeholder, + onChange, + right, + left, + disabled, + id, + defaultValue, + dataTestId, + textAlign = 'left', + ...props + }) => { + const handleChange = useCallback( + (e: React.ChangeEvent) => { + onChange(e, e.target.value.replace(/,/g, '.').replace(/[e+-]/gi, '')); + }, + [onChange] + ); - return ( - - {typeof left === 'string' ? {left} : left} - - { - if (INVALID_CHARS.includes(e.key)) { - e.preventDefault(); - } - }} - id={id} - defaultValue={defaultValue} - /> - {typeof right === 'string' ? {right} : right} - - ); -}; + return ( + + {typeof left === 'string' ? {left} : left} + { + if (INVALID_CHARS.includes(e.key)) { + e.preventDefault(); + } + }} + id={id} + defaultValue={defaultValue} + /> + {typeof right === 'string' ? {right} : right} + + ); + } +); const CustomInputContainer = styled.div<{ textAlign: string; invalid?: boolean }>` display: flex; diff --git a/components/Input/CustomNumericInput.tsx b/components/Input/CustomNumericInput.tsx index 50f2cf8e10..4bb71295f7 100644 --- a/components/Input/CustomNumericInput.tsx +++ b/components/Input/CustomNumericInput.tsx @@ -1,4 +1,4 @@ -import { ChangeEvent, FC } from 'react'; +import { ChangeEvent, FC, memo } from 'react'; import styled from 'styled-components'; import Input from './Input'; @@ -15,63 +15,61 @@ type CustomNumericInputProps = { id?: string; }; -const CustomNumericInput: FC = ({ - value, - placeholder, - suffix, - onChange, - className, - defaultValue, - maxValue, - disabled, - id, - ...rest -}) => { - const style = { - '--numchs': value.length, - '--suffix': `'${value.length === 0 ? '' : suffix}'`, - }; +const CustomNumericInput: FC = memo( + ({ + value, + placeholder, + suffix, + onChange, + className, + defaultValue, + maxValue, + disabled, + id, + ...rest + }) => { + const handleOnChange = (e: ChangeEvent) => { + const { value } = e.target; + const max = maxValue || 0; + const valueIsAboveMax = max !== 0 && Number(value) > max; + if (!valueIsAboveMax) { + onChange( + e, + value + .replace(/[^0-9.,]/g, '') + .replace(/,/g, '.') + .substring(0, 4) + ); + } + }; - const handleOnChange = (e: ChangeEvent) => { - const { value } = e.target; - const max = maxValue || 0; - const valueIsAboveMax = max !== 0 && Number(value) > max; - if (!valueIsAboveMax) { - onChange( - e, - value - .replace(/[^0-9.,]/g, '') - .replace(/,/g, '.') - .substring(0, 4) - ); - } - }; - - return ( - - - - ); -}; + return ( + + + + ); + } +); -export const InputWrapper = styled.div` +export const InputWrapper = styled.div<{ $length: number; $suffix: string }>` position: relative; overflow: hidden; ::after { position: absolute; top: calc(25%); - left: calc((var(--numchs) * 1ch + 1.3ch)); - content: var(--suffix, 'x'); + left: calc(${(props) => props.$length} * 1ch + 1.3ch)); + content: var(${(props) => (props.$length === 0 ? '' : props.$suffix)}); font-family: ${(props) => props.theme.fonts.mono}; font-size: 18px; color: ${(props) => props.theme.colors.selectedTheme.input.placeholder}; diff --git a/components/Input/InputBalanceLabel.tsx b/components/Input/InputBalanceLabel.tsx index ebfdf92abe..7acbccb5a0 100644 --- a/components/Input/InputBalanceLabel.tsx +++ b/components/Input/InputBalanceLabel.tsx @@ -2,7 +2,7 @@ import Wei from '@synthetixio/wei'; import { useTranslation } from 'react-i18next'; import styled from 'styled-components'; -import { FlexDivRowCentered } from 'styles/common'; +import { FlexDivRowCentered } from 'components/layout/flex'; import { formatCurrency } from 'utils/formatters/number'; type Props = { diff --git a/components/Input/NumericInput.tsx b/components/Input/NumericInput.tsx index 8b5332bfc6..7b4d976ec7 100644 --- a/components/Input/NumericInput.tsx +++ b/components/Input/NumericInput.tsx @@ -1,9 +1,9 @@ -import { ChangeEvent, FC, memo, useCallback } from 'react'; -import styled from 'styled-components'; +import React, { ChangeEvent, FC, memo, useCallback } from 'react'; +import styled, { css } from 'styled-components'; import Input from './Input'; -type NumericInputProps = { +type NumericInputProps = Omit, 'onChange'> & { value: string | number; placeholder?: string; onChange: (e: ChangeEvent, value: string) => void; @@ -11,46 +11,42 @@ type NumericInputProps = { defaultValue?: any; disabled?: boolean; id?: string; + bold?: boolean; }; const INVALID_CHARS = ['-', '+', 'e']; -const NumericInput: FC = memo( - ({ value, onChange, placeholder, className, defaultValue, disabled, id, ...rest }) => { - const handleOnChange = useCallback( - (e: ChangeEvent) => { - const { value } = e.target; - - onChange(e, value.replace(/,/g, '.').replace(/[e+-]/gi, '')); - }, - [onChange] - ); - - return ( - { - if (INVALID_CHARS.includes(e.key)) { - e.preventDefault(); - } - }} - min="0" - step="any" - defaultValue={defaultValue} - disabled={disabled} - id={id} - /> - ); - } -); - -export const StyledInput = styled(Input)` +const NumericInput: FC = memo(({ onChange, bold, ...props }) => { + const handleOnChange = useCallback( + (e: ChangeEvent) => { + onChange(e, e.target.value.replace(/,/g, '.').replace(/[e+-]/gi, '')); + }, + [onChange] + ); + + return ( + { + if (INVALID_CHARS.includes(e.key)) { + e.preventDefault(); + } + }} + $bold={bold} + {...props} + /> + ); +}); + +export const StyledInput = styled(Input)<{ $bold?: boolean }>` font-family: ${(props) => props.theme.fonts.mono}; + ${(props) => + props.$bold && + css` + font-family: ${props.theme.fonts.monoBold}; + `} text-overflow: ellipsis; `; diff --git a/components/Loader/Loader.tsx b/components/Loader/Loader.tsx index d7674caac4..9ce740d111 100644 --- a/components/Loader/Loader.tsx +++ b/components/Loader/Loader.tsx @@ -1,4 +1,4 @@ -import { FC } from 'react'; +import { memo, FC } from 'react'; import LoaderIcon from 'assets/svg/app/loader.svg'; import { AbsoluteCenteredDiv } from 'styles/common'; @@ -10,23 +10,19 @@ type LoaderProps = { style?: Record; }; -export const Loader: FC = ({ - inline, - width = '38px', - height = '38px', - style = {}, - ...rest -}) => { - const loader = ; +export const Loader: FC = memo( + ({ inline, width = '38px', height = '38px', style = {}, ...rest }) => { + const loader = ; - return inline ? loader : {loader}; -}; + return inline ? loader : {loader}; + } +); Loader.defaultProps = { inline: false, }; -export const MiniLoader: FC = (props) => { +export const MiniLoader: FC = memo((props) => { return ( = (props) => { style={{ marginLeft: `${!props.centered ? '10px' : '0px'}` }} /> ); -}; +}); -export const ButtonLoader = () => { +export const ButtonLoader = memo(() => { return ; -}; +}); export default Loader; diff --git a/components/MarketClosureIcon/MarketClosureIcon.tsx b/components/MarketClosureIcon/MarketClosureIcon.tsx index ad959f0f7b..30d972ef04 100644 --- a/components/MarketClosureIcon/MarketClosureIcon.tsx +++ b/components/MarketClosureIcon/MarketClosureIcon.tsx @@ -1,4 +1,4 @@ -import React, { FC } from 'react'; +import { FC, memo } from 'react'; import CircuitBreakerIcon from 'assets/svg/app/market-closure/circuit-breaker.svg'; import EmergencyShutdownIcon from 'assets/svg/app/market-closure/emergency-shutdown.svg'; @@ -11,30 +11,26 @@ type MarketClosureIconProps = { size?: 'sm' | 'lg'; }; -export const MarketClosureIcon: FC = ({ - marketClosureReason, - size = 'lg', -}) => { - const sharedProps = { - width: size === 'sm' ? 16 : 32, - height: size === 'sm' ? 16 : 32, - className: 'market-closure-icon', - }; +export const MarketClosureIcon: FC = memo( + ({ marketClosureReason, size = 'lg' }) => { + const sharedProps = { + width: size === 'sm' ? 16 : 32, + height: size === 'sm' ? 16 : 32, + className: 'market-closure-icon', + }; - const defaultIcon = ; - - switch (marketClosureReason) { - case 'frozen': - return ; - case 'market-closure': - return defaultIcon; - case 'circuit-breaker': - return ; - case 'emergency': - return ; - default: - return defaultIcon; + switch (marketClosureReason) { + case 'frozen': + return ; + case 'circuit-breaker': + return ; + case 'emergency': + return ; + case 'market-closure': + default: + return ; + } } -}; +); export default MarketClosureIcon; diff --git a/components/Nav/DropDownLabel.tsx b/components/Nav/DropDownLabel.tsx index e69dabe02c..f36a278cd4 100644 --- a/components/Nav/DropDownLabel.tsx +++ b/components/Nav/DropDownLabel.tsx @@ -1,6 +1,6 @@ import styled from 'styled-components'; -import { FlexDivRow } from 'styles/common'; +import { FlexDivRow } from 'components/layout/flex'; export const LabelContainer = styled(FlexDivRow)<{ noPadding?: boolean }>` padding: ${(props) => !props.noPadding && '16px'}; diff --git a/components/PoweredBySynthetix/PoweredBySynthetix.tsx b/components/PoweredBySynthetix/PoweredBySynthetix.tsx index 52a968a728..6a2b6cd6df 100644 --- a/components/PoweredBySynthetix/PoweredBySynthetix.tsx +++ b/components/PoweredBySynthetix/PoweredBySynthetix.tsx @@ -3,8 +3,10 @@ import { useTranslation } from 'react-i18next'; import styled from 'styled-components'; import TextLogo from 'assets/svg/brand/text-logo-white.svg'; +import { FlexDivColCentered } from 'components/layout/flex'; +import { Body } from 'components/Text'; import { EXTERNAL_LINKS } from 'constants/links'; -import { ExternalLink, FlexDivColCentered, Paragraph } from 'styles/common'; +import { ExternalLink } from 'styles/common'; const PoweredBySynthetix = () => { const { t } = useTranslation(); @@ -22,13 +24,12 @@ const Container = styled(FlexDivColCentered)` row-gap: 5px; `; -const Text = styled(Paragraph)` +const Text = styled(Body)` font-size: 10px; color: ${(props) => props.theme.colors.common.primaryWhite}; opacity: 0.5; letter-spacing: 0.04em; font-variant: small-caps; - font-family: ${(props) => props.theme.fonts.regular}; text-transform: uppercase; line-height: 100%; text-align: center; diff --git a/components/PreviewArrow/PreviewArrow.tsx b/components/PreviewArrow/PreviewArrow.tsx index 051471eb59..d11ef4a60e 100644 --- a/components/PreviewArrow/PreviewArrow.tsx +++ b/components/PreviewArrow/PreviewArrow.tsx @@ -1,20 +1,26 @@ +import { memo } from 'react'; import styled from 'styled-components'; +import { MiniLoader } from 'components/Loader'; + type TextColor = 'yellow' | 'red'; type PreviewArrowProps = { color?: TextColor; showPreview: boolean; + loading?: boolean; }; -const PreviewArrow: React.FC = ({ showPreview, children, color }) => { - return showPreview ? ( - <> - - {children} - - ) : null; -}; +const PreviewArrow: React.FC = memo( + ({ showPreview, children, color, loading }) => { + return showPreview ? ( + <> + + {loading ? : children} + + ) : null; + } +); const StyledArrow = styled.span` ::before { diff --git a/components/ProgressBar/ProgressBar.tsx b/components/ProgressBar/ProgressBar.tsx deleted file mode 100644 index 48a0637b6e..0000000000 --- a/components/ProgressBar/ProgressBar.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import { FC } from 'react'; -import styled from 'styled-components'; - -type ProgressBarProps = { - percentage: number; -}; - -const ProgressBar: FC = ({ percentage }) => ( - - - -); - -const ProgressBarWrapper = styled.div` - background-color: ${(props) => props.theme.colors.navy}; -`; - -const Bar = styled.div<{ percentage: number }>` - height: 100%; - width: ${(props) => props.percentage * 100}%; - height: 4px; - background: ${(props) => props.theme.colors.gold}; -`; - -export default ProgressBar; diff --git a/components/ProgressBar/index.ts b/components/ProgressBar/index.ts deleted file mode 100644 index 84bf041ae7..0000000000 --- a/components/ProgressBar/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './ProgressBar'; diff --git a/components/ProgressSteps/ProgressSteps.tsx b/components/ProgressSteps/ProgressSteps.tsx index 63af4bc8b7..062a1c1b36 100644 --- a/components/ProgressSteps/ProgressSteps.tsx +++ b/components/ProgressSteps/ProgressSteps.tsx @@ -1,4 +1,4 @@ -import { FC } from 'react'; +import { FC, memo } from 'react'; import styled from 'styled-components'; type Props = { @@ -7,7 +7,7 @@ type Props = { complete?: boolean; }; -const ProgressSteps: FC = ({ step, totalSteps, complete }) => { +const ProgressSteps: FC = memo(({ step, totalSteps, complete }) => { const stepList = [...Array(totalSteps)]; return (
@@ -30,7 +30,7 @@ const ProgressSteps: FC = ({ step, totalSteps, complete }) => {
); -}; +}); const BAR_HEIGHT = 3; const CIRCLE_HEIGHT = 18; diff --git a/components/README.md b/components/README.md new file mode 100644 index 0000000000..90bfef15f2 --- /dev/null +++ b/components/README.md @@ -0,0 +1,3 @@ +# Kwenta Components + +## Folder Structure diff --git a/components/StakeCard/StakeCard.tsx b/components/StakeCard/StakeCard.tsx index 969dbe38a6..dc722ec45d 100644 --- a/components/StakeCard/StakeCard.tsx +++ b/components/StakeCard/StakeCard.tsx @@ -5,10 +5,11 @@ import styled from 'styled-components'; import Button from 'components/Button'; import NumericInput from 'components/Input/NumericInput'; +import { FlexDivRowCentered } from 'components/layout/flex'; import SegmentedControl from 'components/SegmentedControl'; +import { StakingCard } from 'sections/dashboard/Stake/card'; import { DEFAULT_CRYPTO_DECIMALS, DEFAULT_TOKEN_DECIMALS } from 'constants/defaults'; -import { StakingCard } from 'sections/dashboard/Stake/common'; -import { FlexDivRowCentered, numericValueCSS } from 'styles/common'; +import { numericValueCSS } from 'styles/common'; import { toWei, truncateNumbers } from 'utils/formatters/number'; type StakeCardProps = { @@ -111,7 +112,7 @@ const StakeCard: FC = memo(
- +
), accessor: 'market', - Cell: (cellProps: CellProps) => { + Cell: (cellProps: CellProps) => { return (
@@ -290,7 +288,7 @@ const FuturesMarketsTable: FC = () => { {cellProps.row.original.market} {
), accessor: 'openInterest', - Cell: (cellProps: CellProps) => { + Cell: (cellProps: CellProps) => { return (
{
), accessor: '24h-change', - Cell: (cellProps: CellProps) => { + Cell: (cellProps: CellProps) => { return (
@@ -359,7 +357,7 @@ const FuturesMarketsTable: FC = () => {
props.theme.colors.selectedTheme.gray}; @@ -423,10 +420,6 @@ const StyledTable = styled(Table)` margin-bottom: 20px; `; -const TableHeader = styled.div` - color: ${(props) => props.theme.colors.selectedTheme.gray}; -`; - const StyledText = styled.div` display: flex; align-items: center; diff --git a/sections/dashboard/FuturesPositionsTable/FuturesPositionsTable.tsx b/sections/dashboard/FuturesPositionsTable/FuturesPositionsTable.tsx index 8bb8cb9662..24d36efd9f 100644 --- a/sections/dashboard/FuturesPositionsTable/FuturesPositionsTable.tsx +++ b/sections/dashboard/FuturesPositionsTable/FuturesPositionsTable.tsx @@ -39,7 +39,7 @@ type FuturesPositionTableProps = { const FuturesPositionsTable: FC = ({ accountType, showCurrentMarket = true, -}: FuturesPositionTableProps) => { +}) => { const { t } = useTranslation(); const { synthsMap } = Connector.useContainer(); const router = useRouter(); @@ -167,9 +167,9 @@ const FuturesPositionsTable: FC = ({ return ( @@ -204,9 +204,9 @@ const FuturesPositionsTable: FC = ({
@@ -231,9 +231,9 @@ const FuturesPositionsTable: FC = ({ {NO_VALUE} ) : ( @@ -255,9 +255,9 @@ const FuturesPositionsTable: FC = ({ }; return ( diff --git a/sections/dashboard/FuturesPositionsTable/MobilePositionRow.tsx b/sections/dashboard/FuturesPositionsTable/MobilePositionRow.tsx index c67c269e19..fe18a5fac6 100644 --- a/sections/dashboard/FuturesPositionsTable/MobilePositionRow.tsx +++ b/sections/dashboard/FuturesPositionsTable/MobilePositionRow.tsx @@ -1,5 +1,5 @@ import { wei } from '@synthetixio/wei'; -import React from 'react'; +import { memo, FC } from 'react'; import styled, { css } from 'styled-components'; import { border } from 'components/Button'; @@ -18,7 +18,7 @@ type MobilePositionRowProps = { onClick(): void; }; -const MobilePositionRow: React.FC = ({ row, onClick }) => { +const MobilePositionRow: FC = memo(({ row, onClick }) => { const prices = useAppSelector(selectPrices); const marketPrice = prices[row.market.asset]?.offChain ?? prices[row.market.asset]?.onChain ?? wei(0); @@ -44,7 +44,7 @@ const MobilePositionRow: React.FC = ({ row, onClick }) =
= ({ row, onClick }) =
= ({ row, onClick }) =
- +
); -}; +}); const OpenPositionContainer = styled.div<{ side?: PositionSide }>` display: flex; diff --git a/sections/dashboard/FuturesPositionsTable/constants.ts b/sections/dashboard/FuturesPositionsTable/constants.ts deleted file mode 100644 index e696e136f8..0000000000 --- a/sections/dashboard/FuturesPositionsTable/constants.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { NO_VALUE } from 'constants/placeholder'; - -export const DEFAULT_DATA = [ - { - asset: NO_VALUE, - market: NO_VALUE, - description: NO_VALUE, - notionalValue: NO_VALUE, - position: NO_VALUE, - avgEntryPrice: undefined, - liquidationPrice: NO_VALUE, - pnl: undefined, - pnlPct: undefined, - margin: NO_VALUE, - leverage: NO_VALUE, - size: undefined, - }, -]; diff --git a/sections/dashboard/MobileDashboard/FuturesMarkets.tsx b/sections/dashboard/MobileDashboard/FuturesMarkets.tsx index ee8414d7fc..5e6d581f0b 100644 --- a/sections/dashboard/MobileDashboard/FuturesMarkets.tsx +++ b/sections/dashboard/MobileDashboard/FuturesMarkets.tsx @@ -2,29 +2,19 @@ import { wei } from '@synthetixio/wei'; import React, { useMemo } from 'react'; import { useTranslation } from 'react-i18next'; -import { SectionHeader, SectionTitle } from 'sections/futures/MobileTrade/common'; -import { selectMarkets, selectMarketVolumes } from 'state/futures/selectors'; +import { HeaderContainer, MarketStatsContainer, MarketStat } from 'sections/dashboard/mobile'; +import { SectionHeader, SectionTitle } from 'sections/futures/mobile'; +import { selectMarketVolumes, selectOpenInterest } from 'state/futures/selectors'; import { useAppSelector } from 'state/hooks'; -import { formatDollars, formatNumber, zeroBN } from 'utils/formatters/number'; +import { formatDollars, formatNumber } from 'utils/formatters/number'; import FuturesMarketsTable from '../FuturesMarketsTable'; -import { HeaderContainer, MarketStatsContainer, MarketStat } from './common'; const FuturesMarkets = () => { const { t } = useTranslation(); - const futuresMarkets = useAppSelector(selectMarkets); const futuresVolumes = useAppSelector(selectMarketVolumes); - - const openInterest = useMemo(() => { - return ( - futuresMarkets.reduce( - (total, { openInterest }) => - total.add(openInterest?.shortUSD ?? wei(0)).add(openInterest?.longUSD ?? wei(0)), - wei(0) - ) ?? null - ); - }, [futuresMarkets]); + const openInterest = useAppSelector(selectOpenInterest); const [trades, volume] = useMemo(() => { const { totalTrades, totalVolume } = Object.values(futuresVolumes).reduce( @@ -32,10 +22,7 @@ const FuturesMarkets = () => { totalTrades: totalTrades.add(trades), totalVolume: totalVolume.add(volume), }), - { - totalTrades: wei(0), - totalVolume: wei(0), - } + { totalTrades: wei(0), totalVolume: wei(0) } ); return [totalTrades, totalVolume]; }, [futuresVolumes]); @@ -51,11 +38,7 @@ const FuturesMarkets = () => {
{t('dashboard.overview.futures-markets-table.daily-volume')}
-
- {formatDollars(volume ?? zeroBN, { - minDecimals: 0, - })} -
+
{formatDollars(volume, { minDecimals: 0 })}
@@ -67,7 +50,7 @@ const FuturesMarkets = () => {
{t('dashboard.overview.futures-markets-table.daily-trades')}
-
{formatNumber(trades ?? 0, { minDecimals: 0 })}
+
{formatNumber(trades, { minDecimals: 0 })}
diff --git a/sections/dashboard/MobileDashboard/MobileDashboard.tsx b/sections/dashboard/MobileDashboard/MobileDashboard.tsx index bb6df11ec8..acd0a11b97 100644 --- a/sections/dashboard/MobileDashboard/MobileDashboard.tsx +++ b/sections/dashboard/MobileDashboard/MobileDashboard.tsx @@ -1,4 +1,3 @@ -import Wei from '@synthetixio/wei'; import { FC } from 'react'; import { useRecoilState } from 'recoil'; @@ -16,7 +15,7 @@ const MobileDashboard: FC = ({ exchangeTokens }) => { const [activePositionsTab, setActivePositionsTab] = useRecoilState(activePositionsTabState); const exchangeTokenBalances = exchangeTokens.reduce( - (initial: Wei, { usdBalance }) => initial.add(usdBalance), + (initial, { usdBalance }) => initial.add(usdBalance), zeroBN ); diff --git a/sections/dashboard/MobileDashboard/OpenPositions.tsx b/sections/dashboard/MobileDashboard/OpenPositions.tsx index d0e8c545c8..fd55f564af 100644 --- a/sections/dashboard/MobileDashboard/OpenPositions.tsx +++ b/sections/dashboard/MobileDashboard/OpenPositions.tsx @@ -5,12 +5,12 @@ import { SetterOrUpdater } from 'recoil'; import styled from 'styled-components'; import TabButton from 'components/Button/TabButton'; +import { SectionHeader, SectionTitle } from 'sections/futures/mobile'; import { TabPanel } from 'components/Tab'; import { FuturesAccountTypes } from 'queries/futures/types'; -import { SectionHeader, SectionTitle } from 'sections/futures/MobileTrade/common'; import { selectBalances } from 'state/balances/selectors'; import { - selectCrossMarginPositions, + // selectCrossMarginPositions, selectFuturesPortfolio, selectIsolatedMarginPositions, } from 'state/futures/selectors'; @@ -43,7 +43,7 @@ const OpenPositions: React.FC = ({ exchangeTokenBalances, }) => { const { t } = useTranslation(); - const crossPositions = useAppSelector(selectCrossMarginPositions); + // const crossPositions = useAppSelector(selectCrossMarginPositions); const isolatedPositions = useAppSelector(selectIsolatedMarginPositions); const portfolio = useAppSelector(selectFuturesPortfolio); const balances = useAppSelector(selectBalances); @@ -80,9 +80,9 @@ const OpenPositions: React.FC = ({ [ t, isolatedPositions, - crossPositions, + // crossPositions, activePositionsTab, - portfolio.crossMarginFutures, + // portfolio.crossMarginFutures, portfolio.isolatedMarginFutures, balances.totalUSDBalance, exchangeTokenBalances, @@ -121,13 +121,10 @@ const OpenPositions: React.FC = ({ const TabButtonsContainer = styled.div` display: flex; - margin-top: 16px; - margin-bottom: 16px; + margin: 16px 0; - & > button { - &:not(:last-of-type) { - margin-right: 14px; - } + & > button:not(:last-of-type) { + margin-right: 14px; } `; diff --git a/sections/dashboard/MobileDashboard/Portfolio.tsx b/sections/dashboard/MobileDashboard/Portfolio.tsx index 922f1128e4..670def5a15 100644 --- a/sections/dashboard/MobileDashboard/Portfolio.tsx +++ b/sections/dashboard/MobileDashboard/Portfolio.tsx @@ -2,7 +2,7 @@ import Wei from '@synthetixio/wei'; import React from 'react'; import { useTranslation } from 'react-i18next'; -import { SectionHeader, SectionTitle } from 'sections/futures/MobileTrade/common'; +import { SectionHeader, SectionTitle } from 'sections/futures/mobile'; import PortfolioChart from '../PortfolioChart'; diff --git a/sections/dashboard/MobileDashboard/SpotMarkets.tsx b/sections/dashboard/MobileDashboard/SpotMarkets.tsx index 24972006d6..57ba29ade6 100644 --- a/sections/dashboard/MobileDashboard/SpotMarkets.tsx +++ b/sections/dashboard/MobileDashboard/SpotMarkets.tsx @@ -2,10 +2,10 @@ import React from 'react'; import { useTranslation } from 'react-i18next'; import styled from 'styled-components'; -import { SectionHeader, SectionTitle } from 'sections/futures/MobileTrade/common'; +import { HeaderContainer } from 'sections/dashboard/mobile'; +import { SectionHeader, SectionTitle } from 'sections/futures/mobile'; import SpotMarketsTable from '../SpotMarketsTable'; -import { HeaderContainer } from './common'; const SpotMarkets: React.FC = () => { const { t } = useTranslation(); diff --git a/sections/dashboard/MobileDashboard/common.ts b/sections/dashboard/MobileDashboard/common.ts deleted file mode 100644 index 3e65c8d7ca..0000000000 --- a/sections/dashboard/MobileDashboard/common.ts +++ /dev/null @@ -1,30 +0,0 @@ -import styled from 'styled-components'; - -export const HeaderContainer = styled.div` - padding: 15px; -`; - -export const MarketStatsContainer = styled.div` - display: grid; - grid-template-columns: 1fr 1fr 1fr; - grid-gap: 8px; -`; - -export const MarketStat = styled.div` - border-radius: 8px; - box-sizing: border-box; - padding: 10px; - border: ${(props) => props.theme.colors.selectedTheme.border}; - - .title { - font-size: 12px; - color: ${(props) => props.theme.colors.selectedTheme.gray}; - margin-bottom: 4px; - } - - .value { - font-size: 16px; - font-family: ${(props) => props.theme.fonts.bold}; - color: ${(props) => props.theme.colors.selectedTheme.text.value}; - } -`; diff --git a/sections/dashboard/Overview/Overview.tsx b/sections/dashboard/Overview/Overview.tsx index 8abf2b70a2..bd96a2b749 100644 --- a/sections/dashboard/Overview/Overview.tsx +++ b/sections/dashboard/Overview/Overview.tsx @@ -15,7 +15,7 @@ import { CompetitionBanner } from 'sections/shared/components/CompetitionBanner' import { selectBalances } from 'state/balances/selectors'; import { sdk } from 'state/config'; import { - selectActiveCrossPositionsCount, + // selectActiveCrossPositionsCount, selectActiveIsolatedPositionsCount, selectFuturesPortfolio, } from 'state/futures/selectors'; @@ -44,12 +44,10 @@ const Overview: FC = () => { const balances = useAppSelector(selectBalances); const portfolio = useAppSelector(selectFuturesPortfolio); const isolatedPositionsCount = useAppSelector(selectActiveIsolatedPositionsCount); - const crossPositionsCount = useAppSelector(selectActiveCrossPositionsCount); + // const crossPositionsCount = useAppSelector(selectActiveCrossPositionsCount); - const [activePositionsTab, setActivePositionsTab] = useRecoilState( - activePositionsTabState - ); - const [activeMarketsTab, setActiveMarketsTab] = useState(MarketsTab.FUTURES); + const [activePositionsTab, setActivePositionsTab] = useRecoilState(activePositionsTabState); + const [activeMarketsTab, setActiveMarketsTab] = useState(MarketsTab.FUTURES); const { network, synthsMap } = Connector.useContainer(); @@ -147,13 +145,13 @@ const Overview: FC = () => { }, ]; }, [ - crossPositionsCount, + // crossPositionsCount, isolatedPositionsCount, exchangeTokens, balances.totalUSDBalance, t, activePositionsTab, - portfolio.crossMarginFutures, + // portfolio.crossMarginFutures, portfolio.isolatedMarginFutures, setActivePositionsTab, ]); diff --git a/sections/dashboard/PortfolioChart/PortfolioChart.tsx b/sections/dashboard/PortfolioChart/PortfolioChart.tsx index 286900d4f6..63c84d151b 100644 --- a/sections/dashboard/PortfolioChart/PortfolioChart.tsx +++ b/sections/dashboard/PortfolioChart/PortfolioChart.tsx @@ -4,6 +4,7 @@ import styled from 'styled-components'; import Currency from 'components/Currency'; import { MobileHiddenView, MobileOnlyView } from 'components/Media'; +import * as Text from 'components/Text'; import { selectBalances } from 'state/balances/selectors'; import { selectFuturesPortfolio } from 'state/futures/selectors'; import { useAppSelector } from 'state/hooks'; @@ -27,11 +28,11 @@ const PortfolioChart: FC = ({ exchangeTokenBalances }) => { Portfolio Value - + - + @@ -45,14 +46,12 @@ const Chart = styled.div` height: 200px; `; -const PortfolioTitle = styled.p` +const PortfolioTitle = styled(Text.Body).attrs({ variant: 'bold' })` color: ${(props) => props.theme.colors.selectedTheme.gray}; - font-family: ${(props) => props.theme.fonts.bold}; font-size: 16px; - margin-top: 26px; - margin-left: 26px; - margin-bottom: 10px; + margin: 26px 0 10px 26px; `; + const PortfolioText = styled(Currency.Price)` color: ${(props) => props.theme.colors.selectedTheme.button.text.primary}; font-family: ${(props) => props.theme.fonts.monoBold}; diff --git a/sections/dashboard/SpotHistoryTable/SpotHistoryTable.tsx b/sections/dashboard/SpotHistoryTable/SpotHistoryTable.tsx index a9ef3b87a8..c58d559b20 100644 --- a/sections/dashboard/SpotHistoryTable/SpotHistoryTable.tsx +++ b/sections/dashboard/SpotHistoryTable/SpotHistoryTable.tsx @@ -1,6 +1,4 @@ import { SynthExchangeResult } from '@synthetixio/queries'; -import * as _ from 'lodash/fp'; -import values from 'lodash/values'; import Link from 'next/link'; import { FC, useMemo, ReactElement } from 'react'; import { useTranslation } from 'react-i18next'; @@ -29,20 +27,20 @@ type WalletTradesExchangeResult = Omit & timestamp: number; }; +const conditionalRender = (prop: T, children: ReactElement) => + !prop ?

{NO_VALUE}

: children; + const SpotHistoryTable: FC = () => { const { t } = useTranslation(); const { network, walletAddress, synthsMap } = Connector.useContainer(); const { selectPriceCurrencyRate, selectedPriceCurrency } = useSelectedPriceCurrency(); const walletTradesQuery = useGetWalletTrades(walletAddress!); - const synths = useMemo(() => values(synthsMap) || [], [synthsMap]); + const synths = useMemo(() => Object.values(synthsMap) || [], [synthsMap]); const trades = useMemo(() => { const t = walletTradesQuery.data?.synthExchanges ?? []; - return t.map((trade: any) => ({ - ...trade, - hash: trade.id.split('-')[0], - })); + return t.map((trade: any) => ({ ...trade, hash: trade.id.split('-')[0] })); }, [walletTradesQuery.data]); const filteredHistoricalTrades = useMemo( @@ -54,9 +52,6 @@ const SpotHistoryTable: FC = () => { [trades, synths] ); - const conditionalRender = (prop: T, children: ReactElement): ReactElement => - _.isNil(prop) ?

{NO_VALUE}

: children; - return ( { return conditionalRender( cellProps.row.original.timestamp, - + ); }, @@ -105,7 +100,7 @@ const SpotHistoryTable: FC = () => { { { : {}; return ( @@ -161,9 +161,9 @@ const SpotMarketsTable: FC = () => { Cell: (cellProps: CellProps) => { return ( ); @@ -258,9 +258,9 @@ const SpotMarketsTable: FC = () => { Cell: (cellProps: CellProps) => { return ( ); diff --git a/sections/dashboard/Stake/EscrowTable.tsx b/sections/dashboard/Stake/EscrowTable.tsx index 0344fb2eb4..cbf1d8cc31 100644 --- a/sections/dashboard/Stake/EscrowTable.tsx +++ b/sections/dashboard/Stake/EscrowTable.tsx @@ -5,13 +5,13 @@ import styled from 'styled-components'; import { DesktopOnlyView, MobileOrTabletView } from 'components/Media'; import Table from 'components/Table'; -import { TableCellHead } from 'components/Table/Table'; +import { TableCellHead, TableHeader } from 'components/Table'; import type { EscrowData } from 'sdk/services/kwentaToken'; +import { StakingCard } from 'sections/dashboard/Stake/card'; import { useAppDispatch, useAppSelector } from 'state/hooks'; import { vestEscrowedRewards } from 'state/staking/actions'; import { truncateNumbers, zeroBN } from 'utils/formatters/number'; -import { StakingCard } from './common'; import VestConfirmationModal from './VestConfirmationModal'; const EscrowTable = () => { @@ -102,7 +102,9 @@ const EscrowTable = () => { width: 40, }, { - Header: () => {t('dashboard.stake.tabs.escrow.date')}, + Header: () => ( + {t('dashboard.stake.tabs.escrow.date')} + ), Cell: (cellProps: CellProps) => ( {cellProps.row.original.date} ), @@ -111,7 +113,7 @@ const EscrowTable = () => { }, { Header: () => ( - +
{t('dashboard.stake.tabs.escrow.time-until-vestable')}
), @@ -123,7 +125,7 @@ const EscrowTable = () => { }, { Header: () => ( - +
{t('dashboard.stake.tabs.escrow.immediately-vestable')}
), @@ -134,7 +136,9 @@ const EscrowTable = () => { width: 80, }, { - Header: () => {t('dashboard.stake.tabs.escrow.amount')}, + Header: () => ( + {t('dashboard.stake.tabs.escrow.amount')} + ), Cell: (cellProps: CellProps) => ( {truncateNumbers(cellProps.row.original.amount, 4)} ), @@ -143,7 +147,7 @@ const EscrowTable = () => { }, { Header: () => ( - +
{t('dashboard.stake.tabs.escrow.early-vest-fee')}
), @@ -154,7 +158,9 @@ const EscrowTable = () => { width: 80, }, { - Header: () => {t('dashboard.stake.tabs.escrow.status')}, + Header: () => ( + {t('dashboard.stake.tabs.escrow.status')} + ), Cell: (cellProps: CellProps) => ( {cellProps.row.original.status} ), @@ -186,7 +192,9 @@ const EscrowTable = () => { width: 40, }, { - Header: () => {t('dashboard.stake.tabs.escrow.amount')}, + Header: () => ( + {t('dashboard.stake.tabs.escrow.amount')} + ), Cell: (cellProps: CellProps) => ( {truncateNumbers(cellProps.row.original.amount, 4)} ), @@ -195,7 +203,7 @@ const EscrowTable = () => { }, { Header: () => ( - {t('dashboard.stake.tabs.escrow.early-vest-fee')} + {t('dashboard.stake.tabs.escrow.early-vest-fee')} ), Cell: (cellProps: CellProps) => ( {truncateNumbers(cellProps.row.original.fee, 4)} @@ -204,7 +212,9 @@ const EscrowTable = () => { width: 80, }, { - Header: () => {t('dashboard.stake.tabs.escrow.status')}, + Header: () => ( + {t('dashboard.stake.tabs.escrow.status')} + ), Cell: (cellProps: CellProps) => ( {cellProps.row.original.status} ), @@ -264,12 +274,6 @@ const StyledTable = styled(Table)` } `; -const TableHeader = styled.div` - font-size: 10px; - font-family: ${(props) => props.theme.fonts.regular}; - color: ${(props) => props.theme.colors.selectedTheme.text.header}; -`; - const TableCell = styled.div` font-size: 11px; color: ${(props) => props.theme.colors.selectedTheme.button.text.primary}; diff --git a/sections/dashboard/Stake/InputCards/RedeemInputCard.tsx b/sections/dashboard/Stake/InputCards/RedeemInputCard.tsx index 2051161ded..8611849f4a 100644 --- a/sections/dashboard/Stake/InputCards/RedeemInputCard.tsx +++ b/sections/dashboard/Stake/InputCards/RedeemInputCard.tsx @@ -3,6 +3,8 @@ import { useTranslation } from 'react-i18next'; import styled from 'styled-components'; import Button from 'components/Button'; +import { FlexDivRowCentered } from 'components/layout/flex'; +import { StakingCard } from 'sections/dashboard/Stake/card'; import { useAppDispatch, useAppSelector } from 'state/hooks'; import { approveKwentaToken, redeemToken } from 'state/staking/actions'; import { @@ -11,11 +13,9 @@ import { selectVeKwentaBalance, selectVKwentaBalance, } from 'state/staking/selectors'; -import { FlexDivRowCentered, numericValueCSS } from 'styles/common'; +import { numericValueCSS } from 'styles/common'; import { truncateNumbers } from 'utils/formatters/number'; -import { StakingCard } from '../common'; - type RedeemInputCardProps = { inputLabel: string; isVKwenta: boolean; diff --git a/sections/dashboard/Stake/RedemptionTab.tsx b/sections/dashboard/Stake/RedemptionTab.tsx index 725b039e83..2067af54b6 100644 --- a/sections/dashboard/Stake/RedemptionTab.tsx +++ b/sections/dashboard/Stake/RedemptionTab.tsx @@ -1,7 +1,6 @@ import { useTranslation } from 'react-i18next'; -import styled from 'styled-components'; -import media from 'styles/media'; +import { SplitContainer } from 'components/layout/grid'; import RedeemInputCard from './InputCards/RedeemInputCard'; @@ -9,34 +8,14 @@ const RedemptionTab = () => { const { t } = useTranslation(); return ( - + - + ); }; -const StakingTabContainer = styled.div` - ${media.greaterThan('mdUp')` - display: grid; - grid-template-columns: 1fr 1fr; - & > div { - flex: 1; - - &:first-child { - margin-right: 15px; - } - } - `} - - ${media.lessThan('mdUp')` - & > div:first-child { - margin-bottom: 15px; - } - `} -`; - export default RedemptionTab; diff --git a/sections/dashboard/Stake/StakingPortfolio.tsx b/sections/dashboard/Stake/StakingPortfolio.tsx index ce5addf80c..8790704b20 100644 --- a/sections/dashboard/Stake/StakingPortfolio.tsx +++ b/sections/dashboard/Stake/StakingPortfolio.tsx @@ -3,8 +3,10 @@ import { useTranslation } from 'react-i18next'; import styled from 'styled-components'; import TabButton from 'components/Button/TabButton'; +import { Heading } from 'sections/earn/text'; +import { FlexDivRowCentered } from 'components/layout/flex'; +import { SplitStakingCard } from 'sections/dashboard/Stake/card'; import { EXTERNAL_LINKS } from 'constants/links'; -import { Heading } from 'sections/earn/common'; import { useAppSelector } from 'state/hooks'; import { selectClaimableBalance, @@ -14,12 +16,9 @@ import { selectStakedKwentaBalance, selectTotalVestable, } from 'state/staking/selectors'; -import { FlexDivRowCentered } from 'styles/common'; import media from 'styles/media'; import { truncateNumbers } from 'utils/formatters/number'; -import { SplitStakingCard } from './common'; - export enum StakeTab { Staking = 'staking', Escrow = 'escrow', diff --git a/sections/dashboard/Stake/StakingTab.tsx b/sections/dashboard/Stake/StakingTab.tsx index 44e0f1723d..102d709acd 100644 --- a/sections/dashboard/Stake/StakingTab.tsx +++ b/sections/dashboard/Stake/StakingTab.tsx @@ -3,14 +3,14 @@ import { useTranslation } from 'react-i18next'; import styled from 'styled-components'; import Button from 'components/Button'; +import { SplitContainer } from 'components/layout/grid'; +import { StakingCard } from 'sections/dashboard/Stake/card'; import { LogoText } from 'components/Text'; import { useAppDispatch, useAppSelector } from 'state/hooks'; import { getReward } from 'state/staking/actions'; import { selectAPY, selectClaimableBalance } from 'state/staking/selectors'; -import media from 'styles/media'; import { formatPercent, truncateNumbers } from 'utils/formatters/number'; -import { StakingCard } from './common'; import StakeInputCard from './InputCards/StakeInputCard'; const StakingTab = () => { @@ -25,7 +25,7 @@ const StakingTab = () => { }, [dispatch]); return ( - +
@@ -48,24 +48,10 @@ const StakingTab = () => { - + ); }; -const StakingTabContainer = styled.div` - ${media.greaterThan('mdUp')` - display: grid; - grid-template-columns: 1fr 1fr; - grid-gap: 15px; - `} - - ${media.lessThan('mdUp')` - & > div:first-child { - margin-bottom: 15px; - } - `} -`; - const CardGridContainer = styled(StakingCard)` display: flex; flex-direction: column; diff --git a/sections/dashboard/Stake/StakingTabs.tsx b/sections/dashboard/Stake/StakingTabs.tsx index 267ed04d5b..146999f007 100644 --- a/sections/dashboard/Stake/StakingTabs.tsx +++ b/sections/dashboard/Stake/StakingTabs.tsx @@ -3,6 +3,7 @@ import { useTranslation } from 'react-i18next'; import styled from 'styled-components'; import TabButton from 'components/Button/TabButton'; +import { FlexDivRowCentered } from 'components/layout/flex'; import LabelContainer from 'components/Nav/DropDownLabel'; import Select from 'components/Select'; import { DropdownIndicator, IndicatorSeparator } from 'components/Select/Select'; @@ -11,7 +12,6 @@ import useIsL2 from 'hooks/useIsL2'; import { useAppDispatch, useAppSelector } from 'state/hooks'; import { setSelectedEpoch } from 'state/staking/reducer'; import { selectEpochData, selectSelectedEpoch } from 'state/staking/selectors'; -import { FlexDivRowCentered } from 'styles/common'; import media from 'styles/media'; import EscrowTab from './EscrowTab'; diff --git a/sections/dashboard/Stake/TradingRewardsTab.tsx b/sections/dashboard/Stake/TradingRewardsTab.tsx index cdc0ee121e..b8239dd853 100644 --- a/sections/dashboard/Stake/TradingRewardsTab.tsx +++ b/sections/dashboard/Stake/TradingRewardsTab.tsx @@ -1,14 +1,16 @@ import { wei } from '@synthetixio/wei'; import { BigNumber } from 'ethers'; import { formatEther } from 'ethers/lib/utils.js'; -import { useCallback, useMemo, FC } from 'react'; +import { useCallback, useMemo, FC, memo } from 'react'; import { useTranslation } from 'react-i18next'; import styled from 'styled-components'; import HelpIcon from 'assets/svg/app/question-mark.svg'; import Button from 'components/Button'; -import { LogoText } from 'components/Text'; -import StyledTooltip from 'components/Tooltip/StyledTooltip'; +import { FlexDivRow } from 'components/layout/flex'; +import { SplitContainer } from 'components/layout/grid'; +import { Body, LogoText } from 'components/Text'; +import Tooltip from 'components/Tooltip/Tooltip'; import Connector from 'containers/Connector'; import useGetFile from 'queries/files/useGetFile'; import useGetFuturesFee from 'queries/staking/useGetFuturesFee'; @@ -18,153 +20,148 @@ import { FuturesFeeProps, TradingRewardProps, } from 'queries/staking/utils'; +import { StakingCard } from 'sections/dashboard/Stake/card'; import { useAppDispatch, useAppSelector } from 'state/hooks'; import { claimMultipleRewards } from 'state/staking/actions'; import { selectEpochPeriod, selectResetTime, selectTotalRewards } from 'state/staking/selectors'; -import { FlexDivRow } from 'styles/common'; import media from 'styles/media'; import { formatTruncatedDuration } from 'utils/formatters/date'; import { formatDollars, formatPercent, truncateNumbers, zeroBN } from 'utils/formatters/number'; -import { StakingCard } from './common'; - -const TradingRewardsTab: FC = ({ - period = 0, - start = 0, - end = Math.floor(Date.now() / 1000), -}) => { - const { t } = useTranslation(); - const { walletAddress, network } = Connector.useContainer(); - const dispatch = useAppDispatch(); - - const resetTime = useAppSelector(selectResetTime); - const totalRewards = useAppSelector(selectTotalRewards); - const epochPeriod = useAppSelector(selectEpochPeriod); - - const futuresFeeQuery = useGetFuturesFeeForAccount(walletAddress!, start, end); - const futuresFeePaid = useMemo(() => { - const t: FuturesFeeForAccountProps[] = futuresFeeQuery.data ?? []; - - return t - .map((trade) => formatEther(trade.feesPaid.toString())) - .reduce((acc, curr) => acc.add(wei(curr)), zeroBN); - }, [futuresFeeQuery.data]); - - const totalFuturesFeeQuery = useGetFuturesFee(start, end); - const totalFuturesFeePaid = useMemo(() => { - const t: FuturesFeeProps[] = totalFuturesFeeQuery.data ?? []; - - return t - .map((trade) => formatEther(trade.feesCrossMarginAccounts.toString())) - .reduce((acc, curr) => acc.add(wei(curr)), zeroBN); - }, [totalFuturesFeeQuery.data]); - - const estimatedRewardQuery = useGetFile( - `trading-rewards-snapshots/${network.id === 420 ? `goerli-` : ''}epoch-current.json` - ); - const estimatedReward = useMemo( - () => BigNumber.from(estimatedRewardQuery?.data?.claims[walletAddress!]?.amount ?? 0), - [estimatedRewardQuery?.data?.claims, walletAddress] - ); - const weeklyRewards = useMemo(() => BigNumber.from(estimatedRewardQuery?.data?.tokenTotal ?? 0), [ - estimatedRewardQuery?.data?.tokenTotal, - ]); - - const claimDisabled = useMemo(() => totalRewards.lte(0), [totalRewards]); - - const handleClaim = useCallback(() => { - dispatch(claimMultipleRewards()); - }, [dispatch]); - - const ratio = useMemo(() => { - return wei(weeklyRewards).gt(0) ? wei(estimatedReward).div(wei(weeklyRewards)) : zeroBN; - }, [estimatedReward, weeklyRewards]); - - const showEstimatedValue = useMemo(() => wei(period).eq(epochPeriod), [epochPeriod, period]); - - return ( - - - -
-
- {t('dashboard.stake.tabs.trading-rewards.claimable-rewards-all')} -
- {truncateNumbers(totalRewards, 4)} -
-
-
- {t('dashboard.stake.tabs.trading-rewards.trading-activity-reset')} -
-
- {resetTime > new Date().getTime() / 1000 - ? formatTruncatedDuration(resetTime - new Date().getTime() / 1000) - : t('dashboard.stake.tabs.trading-rewards.pending-for-rewards')} +const TradingRewardsTab: FC = memo( + ({ period = 0, start = 0, end = Math.floor(Date.now() / 1000) }) => { + const { t } = useTranslation(); + const { walletAddress, network } = Connector.useContainer(); + const dispatch = useAppDispatch(); + + const resetTime = useAppSelector(selectResetTime); + const totalRewards = useAppSelector(selectTotalRewards); + const epochPeriod = useAppSelector(selectEpochPeriod); + + const futuresFeeQuery = useGetFuturesFeeForAccount(walletAddress!, start, end); + const futuresFeePaid = useMemo(() => { + const t: FuturesFeeForAccountProps[] = futuresFeeQuery.data ?? []; + + return t + .map((trade) => formatEther(trade.feesPaid.toString())) + .reduce((acc, curr) => acc.add(wei(curr)), zeroBN); + }, [futuresFeeQuery.data]); + + const totalFuturesFeeQuery = useGetFuturesFee(start, end); + const totalFuturesFeePaid = useMemo(() => { + const t: FuturesFeeProps[] = totalFuturesFeeQuery.data ?? []; + + return t + .map((trade) => formatEther(trade.feesCrossMarginAccounts.toString())) + .reduce((acc, curr) => acc.add(wei(curr)), zeroBN); + }, [totalFuturesFeeQuery.data]); + + const estimatedRewardQuery = useGetFile( + `trading-rewards-snapshots/${network.id === 420 ? `goerli-` : ''}epoch-current.json` + ); + const estimatedReward = useMemo( + () => BigNumber.from(estimatedRewardQuery?.data?.claims[walletAddress!]?.amount ?? 0), + [estimatedRewardQuery?.data?.claims, walletAddress] + ); + const weeklyRewards = useMemo( + () => BigNumber.from(estimatedRewardQuery?.data?.tokenTotal ?? 0), + [estimatedRewardQuery?.data?.tokenTotal] + ); + + const claimDisabled = useMemo(() => totalRewards.lte(0), [totalRewards]); + + const handleClaim = useCallback(() => { + dispatch(claimMultipleRewards()); + }, [dispatch]); + + const ratio = useMemo(() => { + return wei(weeklyRewards).gt(0) ? wei(estimatedReward).div(wei(weeklyRewards)) : zeroBN; + }, [estimatedReward, weeklyRewards]); + + const showEstimatedValue = useMemo(() => wei(period).eq(epochPeriod), [epochPeriod, period]); + + return ( + + + +
+ {t('dashboard.stake.tabs.trading-rewards.claimable-rewards-all')} + {truncateNumbers(totalRewards, 4)}
-
- - - - - - - -
+ {t('dashboard.stake.tabs.trading-rewards.trading-activity-reset')} + + {resetTime > new Date().getTime() / 1000 + ? formatTruncatedDuration(resetTime - new Date().getTime() / 1000) + : t('dashboard.stake.tabs.trading-rewards.pending-for-rewards')} + +
+
+ + + +
+ + + -
+ {t('dashboard.stake.tabs.trading-rewards.future-fee-paid', { EpochPeriod: period, })} - </div> - <div className="value"> + + {formatDollars(futuresFeePaid, { minDecimals: 2 })} - -
+ +
+
+
+ + {t('dashboard.stake.tabs.trading-rewards.fees-paid', { EpochPeriod: period })} + + {formatDollars(totalFuturesFeePaid, { minDecimals: 2 })}
- -
-
- {t('dashboard.stake.tabs.trading-rewards.fees-paid', { EpochPeriod: period })} -
-
{formatDollars(totalFuturesFeePaid, { minDecimals: 2 })}
-
- {showEstimatedValue ? ( - <> -
-
- {t('dashboard.stake.tabs.trading-rewards.estimated-rewards')} + {showEstimatedValue ? ( + <> +
+ {t('dashboard.stake.tabs.trading-rewards.estimated-rewards')} + {truncateNumbers(wei(estimatedReward), 4)}
- {truncateNumbers(wei(estimatedReward), 4)} -
-
-
- {t('dashboard.stake.tabs.trading-rewards.estimated-reward-share', { - EpochPeriod: period, - })} +
+ + {t('dashboard.stake.tabs.trading-rewards.estimated-reward-share', { + EpochPeriod: period, + })} + + {formatPercent(ratio, { minDecimals: 2 })}
-
{formatPercent(ratio, { minDecimals: 2 })}
-
- + + ) : null} + + {showEstimatedValue ? ( + + {t('dashboard.stake.tabs.trading-rewards.estimated-info')} + ) : null} - - {showEstimatedValue ? ( - - {t('dashboard.stake.tabs.trading-rewards.estimated-info')} - - ) : null} - - - ); -}; + + + ); + } +); const PeriodLabel = styled.div` font-size: 13px; @@ -175,7 +172,7 @@ const PeriodLabel = styled.div` color: ${(props) => props.theme.colors.selectedTheme.gray}; `; -const CustomStyledTooltip = styled(StyledTooltip)` +const CustomStyledTooltip = styled(Tooltip)` padding: 0px 10px 0px; ${media.lessThan('md')` width: 310px; @@ -193,39 +190,34 @@ const CardGridContainer = styled(StakingCard)` justify-content: space-between; `; +const Value = styled(Body).attrs({ variant: 'bold', mono: true })` + color: ${(props) => props.theme.colors.selectedTheme.yellow}; + font-size: 26px; + /*margin-top: 5px;*/ + line-height: initial; +`; + +const Title = styled(Body).attrs({ size: 'medium' })` + color: ${(props) => props.theme.colors.selectedTheme.title}; +`; + const CardGrid = styled.div` display: grid; grid-auto-flow: column; grid-template-rows: 1fr 1fr; grid-template-columns: 1fr 1fr; + & > div { margin-bottom: 20px; } - .value { - margin-top: 5px; - } - - svg { - margin-left: 8px; - } - - .title { - color: ${(props) => props.theme.colors.selectedTheme.title}; - } - ${media.lessThan('md')` column-gap: 10px; `} `; -const TradingRewardsContainer = styled.div` - display: grid; - grid-template-columns: 1fr 1fr; - ${media.lessThan('md')` - grid-template-columns: repeat(1, 1fr); - `} - grid-gap: 15px; +const SpacedHelpIcon = styled(HelpIcon)` + margin-left: 8px; `; export default TradingRewardsTab; diff --git a/sections/dashboard/Stake/VestConfirmationModal.tsx b/sections/dashboard/Stake/VestConfirmationModal.tsx index f567a6f98e..42c63e122e 100644 --- a/sections/dashboard/Stake/VestConfirmationModal.tsx +++ b/sections/dashboard/Stake/VestConfirmationModal.tsx @@ -5,9 +5,10 @@ import styled from 'styled-components'; import BaseModal from 'components/BaseModal'; import Button from 'components/Button'; +import { FlexDivRowCentered } from 'components/layout/flex'; import Spacer from 'components/Spacer'; import { EXTERNAL_LINKS } from 'constants/links'; -import { ExternalLink, FlexDivRowCentered } from 'styles/common'; +import { ExternalLink } from 'styles/common'; import { truncateNumbers } from 'utils/formatters/number'; type Props = { diff --git a/sections/dashboard/Stake/common.tsx b/sections/dashboard/Stake/card.ts similarity index 100% rename from sections/dashboard/Stake/common.tsx rename to sections/dashboard/Stake/card.ts diff --git a/sections/dashboard/SynthBalancesTable/SynthBalancesTable.tsx b/sections/dashboard/SynthBalancesTable/SynthBalancesTable.tsx index eba2f0c50d..9f91f36d92 100644 --- a/sections/dashboard/SynthBalancesTable/SynthBalancesTable.tsx +++ b/sections/dashboard/SynthBalancesTable/SynthBalancesTable.tsx @@ -1,7 +1,6 @@ import { CurrencyKey } from '@synthetixio/contracts-interface'; import { SynthBalance } from '@synthetixio/queries'; import Wei, { wei } from '@synthetixio/wei'; -import * as _ from 'lodash/fp'; import { FC, ReactElement, useMemo } from 'react'; import { useTranslation } from 'react-i18next'; import { CellProps, Row } from 'react-table'; @@ -32,18 +31,13 @@ type Cell = { priceChange: Wei | undefined; }; -const calculatePriceChange = (current: Wei | null | undefined, past: Price | undefined) => { - if (_.isNil(current) || _.isNil(past)) { - return undefined; - } - - const priceChange = current.sub(past.price).div(current); - - return priceChange; +const calculatePriceChange = (current?: Wei | null, past?: Price) => { + if (!current || !past) return undefined; + return current.sub(past.price).div(current); }; -const conditionalRender = (prop: T, children: ReactElement): ReactElement => - _.isNil(prop) ? {NO_VALUE} : children; +const conditionalRender = (prop: T, children: ReactElement) => + !prop ? {NO_VALUE} : children; type SynthBalancesTableProps = { exchangeTokens: { @@ -68,9 +62,9 @@ const SynthBalancesTable: FC = ({ exchangeTokens }) => const { currencyKey, balance, usdBalance } = synthBalance; const price = prices[currencyKey].onChain; - const pastPrice = pastRates.find((price: Price) => price.synth === currencyKey); + const pastPrice = pastRates.find((price) => price.synth === currencyKey); + const description = synthsMap?.[currencyKey]?.description ?? ''; - const description = synthsMap != null ? synthsMap[currencyKey]?.description : ''; return { synth: currencyKey, description, @@ -152,9 +146,9 @@ const SynthBalancesTable: FC = ({ exchangeTokens }) => return conditionalRender( cellProps.row.original.usdBalance, ); @@ -177,9 +171,9 @@ const SynthBalancesTable: FC = ({ exchangeTokens }) => return conditionalRender( cellProps.row.original.price, = ({ exchangeTokens }) => {cellProps.row.original.synth} = ({ exchangeTokens }) =>
{formatNumber(cellProps.row.original.balance ?? 0)}
diff --git a/sections/dashboard/mobile.ts b/sections/dashboard/mobile.ts new file mode 100644 index 0000000000..7ec405e8b1 --- /dev/null +++ b/sections/dashboard/mobile.ts @@ -0,0 +1,72 @@ +import styled, { css } from 'styled-components'; + +export const StakingCard = styled.div<{ $noPadding?: boolean }>` + background: ${(props) => props.theme.colors.selectedTheme.surfaceFill}; + padding: 20px; + border-radius: 15px; + border: ${(props) => props.theme.colors.selectedTheme.border}; + + .title { + font-size: 15px; + color: ${(props) => props.theme.colors.selectedTheme.title}; + } + + .value { + font-family: ${(props) => props.theme.fonts.monoBold}; + font-size: 26px; + color: ${(props) => props.theme.colors.selectedTheme.yellow}; + margin-top: 10px; + } + + ${(props) => + props.$noPadding && + css` + padding: 0; + overflow: hidden; + `} +`; + +export const SplitStakingCard = styled(StakingCard)` + display: flex; + padding: 0; + cursor: pointer; + + & > div { + display: flex; + flex: 1; + flex-direction: column; + padding: 30px 0; + padding-left: 30px; + + &:first-of-type { + border-right: ${(props) => props.theme.colors.selectedTheme.border}; + } + } +`; + +export const HeaderContainer = styled.div` + padding: 15px; +`; + +export const MarketStatsContainer = styled.div` + display: grid; + grid-template-columns: 1fr 1fr 1fr; + grid-gap: 8px; +`; + +export const MarketStat = styled.div` + border-radius: 8px; + box-sizing: border-box; + padding: 10px; + border: ${(props) => props.theme.colors.selectedTheme.border}; + .title { + font-size: 12px; + color: ${(props) => props.theme.colors.selectedTheme.gray}; + margin-bottom: 4px; + } + .value { + font-size: 16px; + font-family: ${(props) => props.theme.fonts.bold}; + color: ${(props) => props.theme.colors.selectedTheme.text.value}; + } +`; diff --git a/sections/earn/GridData.tsx b/sections/earn/GridData.tsx index 92d6e66f62..28aac11cb1 100644 --- a/sections/earn/GridData.tsx +++ b/sections/earn/GridData.tsx @@ -29,7 +29,7 @@ const Title = styled(Body)` `; const GridDataContainer = styled.div` - background-color: ${(props) => props.theme.colors.selectedTheme.segmented.button.background}; + background-color: ${(props) => props.theme.colors.selectedTheme.surfaceFill}; padding: 20px 24px 18px; min-height: 95px; border-bottom: ${(props) => props.theme.colors.selectedTheme.border}; diff --git a/sections/earn/StakeGrid.tsx b/sections/earn/StakeGrid.tsx index 9660370ee1..7bff0009fd 100644 --- a/sections/earn/StakeGrid.tsx +++ b/sections/earn/StakeGrid.tsx @@ -1,25 +1,27 @@ import { useCallback } from 'react'; import Button from 'components/Button'; +import { GridContainer } from 'sections/earn/grid'; import useRewardsTimer from 'hooks/useRewardsTimer'; import { claimRewards } from 'state/earn/actions'; import { selectYieldPerDay } from 'state/earn/selectors'; import { useAppDispatch, useAppSelector } from 'state/hooks'; import { toWei, truncateNumbers } from 'utils/formatters/number'; -import { GridContainer } from './common'; import GridData from './GridData'; +const TimeRemainingData = () => { + const endDate = useAppSelector(({ earn }) => earn.endDate); + const timeTillDeadline = useRewardsTimer(new Date(endDate * 1000)); + + return ; +}; + const StakeGrid = () => { const dispatch = useAppDispatch(); - const { earnedRewards, endDate } = useAppSelector(({ earn }) => ({ - earnedRewards: earn.earnedRewards, - endDate: earn.endDate, - })); + const earnedRewards = useAppSelector(({ earn }) => earn.earnedRewards); const yieldPerDay = useAppSelector(selectYieldPerDay); - const timeTillDeadline = useRewardsTimer(new Date(endDate * 1000)); - const handleClaim = useCallback(() => { dispatch(claimRewards()); }, [dispatch]); @@ -39,7 +41,7 @@ const StakeGrid = () => { Claim Rewards - + ); }; diff --git a/sections/earn/StepOne.tsx b/sections/earn/StepOne.tsx index 92cd285432..233192d109 100644 --- a/sections/earn/StepOne.tsx +++ b/sections/earn/StepOne.tsx @@ -1,6 +1,6 @@ import styled from 'styled-components'; -import { Heading, Description } from './common'; +import { Heading, Description } from 'sections/earn/text'; const StepOne = () => { return ( @@ -36,7 +36,7 @@ const BigButton = styled.div` align-items: center; border: ${(props) => props.theme.colors.selectedTheme.border}; border-radius: 15px; - background-color: ${(props) => props.theme.colors.selectedTheme.segmented.button.background}; + background-color: ${(props) => props.theme.colors.selectedTheme.surfaceFill}; `; export default StepOne; diff --git a/sections/earn/StepTwo.tsx b/sections/earn/StepTwo.tsx index dc80cc7ef8..380413dceb 100644 --- a/sections/earn/StepTwo.tsx +++ b/sections/earn/StepTwo.tsx @@ -1,8 +1,8 @@ import styled from 'styled-components'; -import media from 'styles/media'; +import { Heading, Description } from 'sections/earn/text'; +import { SplitContainer } from 'components/layout/grid'; -import { Heading, Description } from './common'; import EarnStakeCard from './EarnStakeCard'; import StakeGrid from './StakeGrid'; @@ -23,26 +23,4 @@ const StepTwoContainer = styled.div` margin-bottom: 50px; `; -const SplitContainer = styled.div` - margin-top: 10px; - - ${media.greaterThan('mdUp')` - display: grid; - grid-template-columns: 1fr 1fr; - & > div { - flex: 1; - - &:first-child { - margin-right: 15px; - } - } - `} - - ${media.lessThan('mdUp')` - & > div:first-child { - margin-bottom: 15px; - } - `} -`; - export default StepTwo; diff --git a/sections/earn/common.tsx b/sections/earn/grid.ts similarity index 62% rename from sections/earn/common.tsx rename to sections/earn/grid.ts index e2f989b650..25c53717fe 100644 --- a/sections/earn/common.tsx +++ b/sections/earn/grid.ts @@ -1,14 +1,7 @@ import styled from 'styled-components'; -import * as Text from 'components/Text'; import media from 'styles/media'; -export const Description = styled(Text.Body)` - font-size: 15px; - color: ${(props) => props.theme.colors.selectedTheme.gray}; - margin: 8px 0; -`; - export const GridContainer = styled.div` display: flex; @@ -17,7 +10,7 @@ export const GridContainer = styled.div` border-radius: 15px; border: ${(props) => props.theme.colors.selectedTheme.border}; overflow: hidden; - background-color: ${(props) => props.theme.colors.selectedTheme.segmented.button.background}; + background-color: ${(props) => props.theme.colors.selectedTheme.surfaceFill}; & > div { box-sizing: border-box; @@ -45,12 +38,3 @@ export const GridContainer = styled.div` flex-direction: column; `} `; - -export const Heading = styled(Text.Heading).attrs({ variant: 'h4' })` - font-family: ${(props) => props.theme.fonts.bold}; - font-size: 21px; - margin-bottom: 4px; - text-transform: uppercase; - font-variant: all-small-caps; - color: ${(props) => props.theme.colors.selectedTheme.yellow}; -`; diff --git a/sections/earn/text.ts b/sections/earn/text.ts new file mode 100644 index 0000000000..51ac1d845e --- /dev/null +++ b/sections/earn/text.ts @@ -0,0 +1,18 @@ +import styled from 'styled-components'; + +import * as Text from 'components/Text'; + +export const Description = styled(Text.Body)` + font-size: 15px; + color: ${(props) => props.theme.colors.selectedTheme.gray}; + margin: 8px 0; +`; + +export const Heading = styled(Text.Heading).attrs({ variant: 'h4' })` + font-family: ${(props) => props.theme.fonts.bold}; + font-size: 21px; + margin-bottom: 4px; + text-transform: uppercase; + font-variant: all-small-caps; + color: ${(props) => props.theme.colors.selectedTheme.yellow}; +`; diff --git a/sections/exchange/BasicSwap/BasicSwap.tsx b/sections/exchange/BasicSwap.tsx similarity index 78% rename from sections/exchange/BasicSwap/BasicSwap.tsx rename to sections/exchange/BasicSwap.tsx index 21a2994d26..3b1c45f1a9 100644 --- a/sections/exchange/BasicSwap/BasicSwap.tsx +++ b/sections/exchange/BasicSwap.tsx @@ -2,12 +2,12 @@ import { FC, memo } from 'react'; import { useTranslation } from 'react-i18next'; import styled from 'styled-components'; -import { BoldText } from 'styles/common'; +import * as Text from 'components/Text'; -import BaseCurrencyCard from '../TradeCard/Cards/BaseCurrencyCard'; -import FooterCard from '../TradeCard/Cards/FooterCard'; -import QuoteCurrencyCard from '../TradeCard/Cards/QuoteCurrencyCard'; import SwapCurrencies from './SwapCurrencies'; +import BaseCurrencyCard from './TradeCard/Cards/BaseCurrencyCard'; +import FooterCard from './TradeCard/Cards/FooterCard'; +import QuoteCurrencyCard from './TradeCard/Cards/QuoteCurrencyCard'; const BasicSwap: FC = memo(() => { const { t } = useTranslation(); @@ -29,7 +29,7 @@ const BasicSwap: FC = memo(() => { export default BasicSwap; -const ExchangeTitle = styled(BoldText)` +const ExchangeTitle = styled(Text.Body).attrs({ variant: 'bold' })` color: ${(props) => props.theme.colors.selectedTheme.button.text.primary}; font-size: 30px; margin-bottom: 1.5em; diff --git a/sections/exchange/BasicSwap/index.ts b/sections/exchange/BasicSwap/index.ts deleted file mode 100644 index f37d73a622..0000000000 --- a/sections/exchange/BasicSwap/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './BasicSwap'; diff --git a/sections/exchange/ExchangeContent/ExchangeContent.tsx b/sections/exchange/ExchangeContent.tsx similarity index 100% rename from sections/exchange/ExchangeContent/ExchangeContent.tsx rename to sections/exchange/ExchangeContent.tsx diff --git a/sections/exchange/ExchangeContent/index.ts b/sections/exchange/ExchangeContent/index.ts deleted file mode 100644 index 18cfec4aa6..0000000000 --- a/sections/exchange/ExchangeContent/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './ExchangeContent'; diff --git a/sections/exchange/ExchangeHead/ExchangeHead.tsx b/sections/exchange/ExchangeHead.tsx similarity index 100% rename from sections/exchange/ExchangeHead/ExchangeHead.tsx rename to sections/exchange/ExchangeHead.tsx diff --git a/sections/exchange/ExchangeHead/index.ts b/sections/exchange/ExchangeHead/index.ts deleted file mode 100644 index 8b549d612e..0000000000 --- a/sections/exchange/ExchangeHead/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './ExchangeHead'; diff --git a/sections/exchange/ExchangeModals/ExchangeModals.tsx b/sections/exchange/ExchangeModals.tsx similarity index 100% rename from sections/exchange/ExchangeModals/ExchangeModals.tsx rename to sections/exchange/ExchangeModals.tsx diff --git a/sections/exchange/ExchangeModals/index.ts b/sections/exchange/ExchangeModals/index.ts deleted file mode 100644 index 2de2fc2469..0000000000 --- a/sections/exchange/ExchangeModals/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './ExchangeModals'; diff --git a/sections/exchange/FooterCard/ConnectWalletCard/ConnectWalletCard.tsx b/sections/exchange/FooterCard/ConnectWalletCard.tsx similarity index 77% rename from sections/exchange/FooterCard/ConnectWalletCard/ConnectWalletCard.tsx rename to sections/exchange/FooterCard/ConnectWalletCard.tsx index cb421ca8a6..c045edf62e 100644 --- a/sections/exchange/FooterCard/ConnectWalletCard/ConnectWalletCard.tsx +++ b/sections/exchange/FooterCard/ConnectWalletCard.tsx @@ -1,16 +1,20 @@ import { useConnectModal } from '@rainbow-me/rainbowkit'; -import { FC } from 'react'; +import { FC, memo } from 'react'; import { useTranslation } from 'react-i18next'; import { DesktopOnlyView, MobileOrTabletView } from 'components/Media'; - -import { MessageButton, MessageContainer, Message, FixedMessageContainerSpacer } from '../common'; +import { + MessageButton, + MessageContainer, + Message, + FixedMessageContainerSpacer, +} from 'sections/exchange/message'; type ConnectWalletCardProps = { className?: string; }; -const ConnectWalletCard: FC = ({ ...rest }) => { +const ConnectWalletCard: FC = memo(({ ...rest }) => { const { t } = useTranslation(); const { openConnectModal: connectWallet } = useConnectModal(); @@ -29,6 +33,6 @@ const ConnectWalletCard: FC = ({ ...rest }) => { ); -}; +}); export default ConnectWalletCard; diff --git a/sections/exchange/FooterCard/ConnectWalletCard/index.ts b/sections/exchange/FooterCard/ConnectWalletCard/index.ts deleted file mode 100644 index 326dd19746..0000000000 --- a/sections/exchange/FooterCard/ConnectWalletCard/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './ConnectWalletCard'; diff --git a/sections/exchange/FooterCard/MarketClosureCard/MarketClosureCard.tsx b/sections/exchange/FooterCard/MarketClosureCard.tsx similarity index 88% rename from sections/exchange/FooterCard/MarketClosureCard/MarketClosureCard.tsx rename to sections/exchange/FooterCard/MarketClosureCard.tsx index 32626f21b7..9b5b894127 100644 --- a/sections/exchange/FooterCard/MarketClosureCard/MarketClosureCard.tsx +++ b/sections/exchange/FooterCard/MarketClosureCard.tsx @@ -1,13 +1,17 @@ -import { FC, useMemo } from 'react'; +import { FC, useMemo, memo } from 'react'; import { Trans, useTranslation } from 'react-i18next'; import { DesktopOnlyView, MobileOrTabletView } from 'components/Media'; import useMarketClosed from 'hooks/useMarketClosed'; +import { + MessageContainer, + Message, + MessageButton, + FixedMessageContainerSpacer, +} from 'sections/exchange/message'; import { useAppSelector } from 'state/hooks'; -import { MessageContainer, Message, MessageButton, FixedMessageContainerSpacer } from '../common'; - -const MarketClosureCard: FC = () => { +const MarketClosureCard: FC = memo(() => { const { t } = useTranslation(); const { quoteCurrencyKey, baseCurrencyKey } = useAppSelector(({ exchange }) => ({ quoteCurrencyKey: exchange.quoteCurrencyKey, @@ -50,6 +54,6 @@ const MarketClosureCard: FC = () => { ); -}; +}); export default MarketClosureCard; diff --git a/sections/exchange/FooterCard/MarketClosureCard/index.ts b/sections/exchange/FooterCard/MarketClosureCard/index.ts deleted file mode 100644 index 3754100794..0000000000 --- a/sections/exchange/FooterCard/MarketClosureCard/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './MarketClosureCard'; diff --git a/sections/exchange/FooterCard/SettleTransactionsCard/SettleTransactionsCard.tsx b/sections/exchange/FooterCard/SettleTransactionsCard.tsx similarity index 92% rename from sections/exchange/FooterCard/SettleTransactionsCard/SettleTransactionsCard.tsx rename to sections/exchange/FooterCard/SettleTransactionsCard.tsx index 64deda8a88..4b712e12d7 100644 --- a/sections/exchange/FooterCard/SettleTransactionsCard/SettleTransactionsCard.tsx +++ b/sections/exchange/FooterCard/SettleTransactionsCard.tsx @@ -1,4 +1,4 @@ -import { FC, useCallback } from 'react'; +import { FC, useCallback, memo } from 'react'; import { useTranslation, Trans } from 'react-i18next'; import styled from 'styled-components'; @@ -6,6 +6,7 @@ import Button from 'components/Button'; import { MobileOrTabletView } from 'components/Media'; import ErrorTooltip from 'components/Tooltip/ErrorTooltip'; import { EXTERNAL_LINKS } from 'constants/links'; +import { MessageContainer, Message, FixedMessageContainerSpacer } from 'sections/exchange/message'; import TxSettleModal from 'sections/shared/modals/TxSettleModal'; import { submitSettle } from 'state/exchange/actions'; import { closeModal } from 'state/exchange/reducer'; @@ -14,9 +15,7 @@ import { NoTextTransform, ExternalLink } from 'styles/common'; import { secondsToTime } from 'utils/formatters/date'; import logError from 'utils/logError'; -import { MessageContainer, Message, FixedMessageContainerSpacer } from '../common'; - -const SettleTransactionsCard: FC = () => { +const SettleTransactionsCard: FC = memo(() => { const { t } = useTranslation(); const { @@ -59,7 +58,7 @@ const SettleTransactionsCard: FC = () => { ]} /> @@ -67,7 +66,7 @@ const SettleTransactionsCard: FC = () => { ]} /> @@ -102,7 +101,7 @@ const SettleTransactionsCard: FC = () => { )} ); -}; +}); const MessageItem = styled(Message)` grid-column-start: 2; diff --git a/sections/exchange/FooterCard/SettleTransactionsCard/index.ts b/sections/exchange/FooterCard/SettleTransactionsCard/index.ts deleted file mode 100644 index 9e3492c9bc..0000000000 --- a/sections/exchange/FooterCard/SettleTransactionsCard/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './SettleTransactionsCard'; diff --git a/sections/exchange/FooterCard/TradeSummaryCard/TradeSummaryCard.tsx b/sections/exchange/FooterCard/TradeSummaryCard.tsx similarity index 77% rename from sections/exchange/FooterCard/TradeSummaryCard/TradeSummaryCard.tsx rename to sections/exchange/FooterCard/TradeSummaryCard.tsx index c1dd347695..42325348fa 100644 --- a/sections/exchange/FooterCard/TradeSummaryCard/TradeSummaryCard.tsx +++ b/sections/exchange/FooterCard/TradeSummaryCard.tsx @@ -4,9 +4,11 @@ import { useTranslation } from 'react-i18next'; import styled from 'styled-components'; import Button from 'components/Button'; -import Card from 'components/Card'; +import Card, { CardBody } from 'components/Card'; import { DesktopOnlyView, MobileOrTabletView } from 'components/Media'; import ErrorTooltip from 'components/Tooltip/ErrorTooltip'; +import { MessageContainer } from 'sections/exchange/message'; +import { SummaryItems } from 'sections/exchange/summary'; import FeeCostSummaryItem from 'sections/shared/components/FeeCostSummary'; import FeeRateSummaryItem from 'sections/shared/components/FeeRateSummary'; import GasPriceSelect from 'sections/shared/components/GasPriceSelect'; @@ -25,22 +27,12 @@ import { import { useAppDispatch, useAppSelector } from 'state/hooks'; import { secondsToTime } from 'utils/formatters/date'; -import { MessageContainer } from '../common'; -import { SummaryItems } from '../common'; - const TradeSummaryCard: FC = memo(() => { - const { t } = useTranslation(); - - const { feeReclaimPeriod, openModal } = useAppSelector(({ exchange }) => ({ - feeReclaimPeriod: exchange.feeReclaimPeriod, - openModal: exchange.openModal, - })); - - const quoteCurrencyKey = useAppSelector(({ exchange }) => exchange.quoteCurrencyKey); const dispatch = useAppDispatch(); - + const openModal = useAppSelector(({ exchange }) => exchange.openModal); const isApproved = useAppSelector(selectIsApproved); + // TODO: Make this a Redux action in itself. const onSubmit = useCallback(() => { if (!isApproved) { dispatch(submitApprove()); @@ -57,31 +49,16 @@ const TradeSummaryCard: FC = memo(() => { <> - + - + - 0} - preset="top" - content={ -
- {t('exchange.errors.fee-reclamation', { - waitingPeriod: secondsToTime(feeReclaimPeriod), - currencyKey: quoteCurrencyKey, - })} -
- } - > - - - -
+
{openModal === 'confirm' && } {openModal === 'approve' && } @@ -137,6 +114,39 @@ const SubmissionButton = ({ onSubmit, isApproved }: any) => { ); }; +type TradeErrorTooltipProps = { + onSubmit(): void; +}; + +const TradeErrorTooltip: FC = memo(({ onSubmit }) => { + const { t } = useTranslation(); + + const isApproved = useAppSelector(selectIsApproved); + const { feeReclaimPeriod, quoteCurrencyKey } = useAppSelector(({ exchange }) => ({ + feeReclaimPeriod: exchange.feeReclaimPeriod, + quoteCurrencyKey: exchange.quoteCurrencyKey, + })); + + return ( + 0} + preset="top" + content={ +
+ {t('exchange.errors.fee-reclamation', { + waitingPeriod: secondsToTime(feeReclaimPeriod), + currencyKey: quoteCurrencyKey, + })} +
+ } + > + + + +
+ ); +}); + const MobileCard = styled(Card)` margin: 2px auto 20px auto; `; diff --git a/sections/exchange/FooterCard/TradeSummaryCard/index.ts b/sections/exchange/FooterCard/TradeSummaryCard/index.ts deleted file mode 100644 index 6c6b3fa6d1..0000000000 --- a/sections/exchange/FooterCard/TradeSummaryCard/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { default } from './TradeSummaryCard'; -export * from './TradeSummaryCard'; diff --git a/sections/exchange/MobileSwap/SwapInfoBox.tsx b/sections/exchange/MobileSwap/SwapInfoBox.tsx index def4b7df1b..09375d42d0 100644 --- a/sections/exchange/MobileSwap/SwapInfoBox.tsx +++ b/sections/exchange/MobileSwap/SwapInfoBox.tsx @@ -7,7 +7,7 @@ import styled from 'styled-components'; import TimerIcon from 'assets/svg/app/timer.svg'; import InfoBox from 'components/InfoBox'; -import StyledTooltip from 'components/Tooltip/StyledTooltip'; +import Tooltip from 'components/Tooltip/Tooltip'; import { NO_VALUE } from 'constants/placeholder'; import { parseGasPriceObject } from 'hooks/useGas'; import useIsL1 from 'hooks/useIsL1'; @@ -80,7 +80,7 @@ const SwapInfoBox: React.FC = () => { .gt(0) ? ( <> {' + '} - { {formatPercent(wei(exchangeFeeRate).sub(baseFeeRate), { minDecimals: 2 })} - + ) : null ) : null} @@ -101,9 +101,7 @@ const SwapInfoBox: React.FC = () => { [t('common.summary.fee-cost')]: { value: feeCost != null - ? formatDollars(feeCost, { - minDecimals: feeCost.lt(0.01) ? 4 : 2, - }) + ? formatDollars(feeCost, { minDecimals: feeCost.lt(0.01) ? 4 : 2 }) : NO_VALUE, }, }} diff --git a/sections/exchange/BasicSwap/SwapCurrencies.tsx b/sections/exchange/SwapCurrencies.tsx similarity index 100% rename from sections/exchange/BasicSwap/SwapCurrencies.tsx rename to sections/exchange/SwapCurrencies.tsx diff --git a/sections/exchange/TradeCard/CurrencyCard/CurrencyCard.tsx b/sections/exchange/TradeCard/CurrencyCard/CurrencyCard.tsx index 58d7f74789..3788653c5d 100644 --- a/sections/exchange/TradeCard/CurrencyCard/CurrencyCard.tsx +++ b/sections/exchange/TradeCard/CurrencyCard/CurrencyCard.tsx @@ -3,8 +3,8 @@ import { FC, useMemo, memo } from 'react'; import { useTranslation } from 'react-i18next'; import styled, { css } from 'styled-components'; -import Card from 'components/Card'; -import { FlexDivRowCentered } from 'styles/common'; +import Card, { CardBody } from 'components/Card'; +import { FlexDivRowCentered } from 'components/layout/flex'; import { Side } from '../types'; import CurrencyCardInput from './CurrencyCardInput'; @@ -117,7 +117,7 @@ const StyledCard = styled(Card)<{ interactive?: boolean }>` `} `; -const StyledCardBody = styled(Card.Body)` +const StyledCardBody = styled(CardBody)` padding: 20px 32px; `; diff --git a/sections/exchange/TradeCard/CurrencyCard/CurrencyCardInput.tsx b/sections/exchange/TradeCard/CurrencyCard/CurrencyCardInput.tsx index 69bfbaa1a1..f94ceaff28 100644 --- a/sections/exchange/TradeCard/CurrencyCard/CurrencyCardInput.tsx +++ b/sections/exchange/TradeCard/CurrencyCard/CurrencyCardInput.tsx @@ -5,9 +5,10 @@ import styled, { css } from 'styled-components'; import Button from 'components/Button'; import NumericInput from 'components/Input/NumericInput'; +import { FlexDivCol, FlexDivRowCentered } from 'components/layout/flex'; import Loader from 'components/Loader'; import useSelectedPriceCurrency from 'hooks/useSelectedPriceCurrency'; -import { CapitalizedText, FlexDivCol, FlexDivRowCentered, numericValueCSS } from 'styles/common'; +import { CapitalizedText, numericValueCSS } from 'styles/common'; import { formatDollars, zeroBN } from 'utils/formatters/number'; type CurrencyCardInputProps = { diff --git a/sections/exchange/TradeCard/CurrencyCard/CurrencyCardSelector.tsx b/sections/exchange/TradeCard/CurrencyCard/CurrencyCardSelector.tsx index 93caf41717..bd2e87aa71 100644 --- a/sections/exchange/TradeCard/CurrencyCard/CurrencyCardSelector.tsx +++ b/sections/exchange/TradeCard/CurrencyCard/CurrencyCardSelector.tsx @@ -6,10 +6,11 @@ import styled, { css } from 'styled-components'; import CaretDownIcon from 'assets/svg/app/caret-down-gray.svg'; import { border } from 'components/Button'; import CurrencyIcon from 'components/Currency/CurrencyIcon'; +import { FlexDivColCentered, FlexDivRow } from 'components/layout/flex'; import { NO_VALUE } from 'constants/placeholder'; import { selectInsufficientBalance } from 'state/exchange/selectors'; import { useAppSelector } from 'state/hooks'; -import { CapitalizedText, FlexDivColCentered, FlexDivRow, numericValueCSS } from 'styles/common'; +import { CapitalizedText, numericValueCSS } from 'styles/common'; import { formatCurrency } from 'utils/formatters/number'; type CurrencyCardSelectorProps = { diff --git a/sections/exchange/TradeCard/CurrencyCard/MobileCurrencyCard.tsx b/sections/exchange/TradeCard/CurrencyCard/MobileCurrencyCard.tsx index 8144b79450..2a8a0ecc15 100644 --- a/sections/exchange/TradeCard/CurrencyCard/MobileCurrencyCard.tsx +++ b/sections/exchange/TradeCard/CurrencyCard/MobileCurrencyCard.tsx @@ -6,9 +6,9 @@ import styled from 'styled-components'; import CaretDownIcon from 'assets/svg/app/caret-down-gray.svg'; import CurrencyIcon from 'components/Currency/CurrencyIcon'; import NumericInput from 'components/Input/NumericInput'; +import { SectionHeader, SectionSubTitle, SectionTitle } from 'sections/futures/mobile'; import { NO_VALUE } from 'constants/placeholder'; import useSelectedPriceCurrency from 'hooks/useSelectedPriceCurrency'; -import { SectionHeader, SectionSubTitle, SectionTitle } from 'sections/futures/MobileTrade/common'; import { formatCurrency, zeroBN } from 'utils/formatters/number'; type MobileCurrencyCardProps = { @@ -140,7 +140,6 @@ const SwapTextInput = styled(NumericInput)` border: none; color: ${(props) => props.theme.colors.selectedTheme.text.value}; font-size: 18px; - font-family: ${(props) => props.theme.fonts.mono}; margin-bottom: 10px; height: initial; diff --git a/sections/exchange/FooterCard/common.tsx b/sections/exchange/message.ts similarity index 63% rename from sections/exchange/FooterCard/common.tsx rename to sections/exchange/message.ts index 0f6ac1c048..6dc77385ff 100644 --- a/sections/exchange/FooterCard/common.tsx +++ b/sections/exchange/message.ts @@ -1,31 +1,15 @@ import styled from 'styled-components'; import Button from 'components/Button'; +import { GridDivCenteredRow } from 'components/layout/grid'; import { zIndex } from 'constants/ui'; -import { FixedFooterMixin, GridDivCenteredRow } from 'styles/common'; +import { FixedFooterMixin } from 'styles/common'; import media from 'styles/media'; -export const SummaryItems = styled.div` - display: grid; - grid-auto-flow: column; - flex-grow: 1; - padding-left: 32px; - justify-content: space-between; - ${media.lessThan('md')` - grid-auto-flow: unset; - grid-template-columns: auto auto; - grid-template-rows: auto auto; - grid-gap: 20px; - `} -`; - -export const MessageContainer = styled(GridDivCenteredRow)<{ - showProvider?: boolean; -}>` +export const MessageContainer = styled(GridDivCenteredRow)` -webkit-box-align: center; width: 100%; border-radius: 4px; - grid-template-columns: ${(props) => props.showProvider && '.5fr'} 1fr; grid-template-rows: 99px 70px; margin: 0 0 20px; diff --git a/sections/shared/components/common.tsx b/sections/exchange/summary.ts similarity index 70% rename from sections/shared/components/common.tsx rename to sections/exchange/summary.ts index 33d6ae35c0..4371fdca45 100644 --- a/sections/shared/components/common.tsx +++ b/sections/exchange/summary.ts @@ -3,6 +3,20 @@ import styled from 'styled-components'; import { numericValueCSS } from 'styles/common'; import media from 'styles/media'; +export const SummaryItems = styled.div` + display: grid; + grid-auto-flow: column; + flex-grow: 1; + padding-left: 32px; + justify-content: space-between; + ${media.lessThan('md')` + grid-auto-flow: unset; + grid-template-columns: auto auto; + grid-template-rows: auto auto; + grid-gap: 20px; + `} +`; + export const SummaryItem = styled.div` display: grid; grid-gap: 4px; diff --git a/sections/futures/CrossMarginOnboard/CrossMarginOnboard.tsx b/sections/futures/CrossMarginOnboard/CrossMarginOnboard.tsx index 07d08e1ba7..9a30811e29 100644 --- a/sections/futures/CrossMarginOnboard/CrossMarginOnboard.tsx +++ b/sections/futures/CrossMarginOnboard/CrossMarginOnboard.tsx @@ -10,9 +10,10 @@ import styled from 'styled-components'; import CompleteCheck from 'assets/svg/futures/onboard-complete-check.svg'; import BaseModal from 'components/BaseModal'; import Button from 'components/Button'; -import ErrorView from 'components/Error'; +import ErrorView from 'components/ErrorView'; import InputBalanceLabel from 'components/Input/InputBalanceLabel'; import NumericInput from 'components/Input/NumericInput'; +import { FlexDivRowCentered } from 'components/layout/flex'; import Loader from 'components/Loader'; import ProgressSteps from 'components/ProgressSteps'; import { CROSS_MARGIN_BASE_SETTINGS } from 'constants/address'; @@ -29,7 +30,6 @@ import useQueryCrossMarginAccount, { import { selectBalances } from 'state/balances/selectors'; import { useAppSelector } from 'state/hooks'; import { futuresAccountState } from 'store/futures'; -import { FlexDivRowCentered } from 'styles/common'; import { isUserDeniedError } from 'utils/formatters/error'; import { zeroBN } from 'utils/formatters/number'; import logError from 'utils/logError'; diff --git a/sections/futures/FeeInfoBox/FeeInfoBox.tsx b/sections/futures/FeeInfoBox/FeeInfoBox.tsx index ec1f9e40bd..dbbfb7f3d6 100644 --- a/sections/futures/FeeInfoBox/FeeInfoBox.tsx +++ b/sections/futures/FeeInfoBox/FeeInfoBox.tsx @@ -1,13 +1,13 @@ import router from 'next/router'; import React, { useMemo, useEffect } from 'react'; import { Trans, useTranslation } from 'react-i18next'; -import styled, { css } from 'styled-components'; +import styled from 'styled-components'; import EligibleIcon from 'assets/svg/app/eligible.svg'; import LinkArrowIcon from 'assets/svg/app/link-arrow.svg'; import NotEligibleIcon from 'assets/svg/app/not-eligible.svg'; import InfoBox, { DetailedInfo } from 'components/InfoBox/InfoBox'; -import * as Text from 'components/Text'; +import { Body } from 'components/Text'; import { NO_VALUE } from 'constants/placeholder'; import ROUTES from 'constants/routes'; import Connector from 'containers/Connector'; @@ -138,7 +138,7 @@ const FeeInfoBox: React.FC = () => { i18nKey={`dashboard.stake.tabs.trading-rewards.stake-to-${ isRewardEligible ? 'earn' : 'start' }`} - components={[]} + components={[]} /> @@ -220,11 +220,7 @@ const StyledLinkArrowIcon = styled(LinkArrowIcon)` cursor: pointer; `; -const Emphasis = styled.b` - font-family: ${(props) => props.theme.fonts.bold}; -`; - -const RewardCopy = styled(Text.Body)` +const RewardCopy = styled(Body)` color: ${(props) => props.theme.colors.selectedTheme.text.title}; `; @@ -243,23 +239,24 @@ const CompactBox = styled.div<{ $isEligible: boolean }>` } .badge-red { - color: ${(props) => props.theme.colors.selectedTheme.badge['red'].text}; - background: ${(props) => props.theme.colors.selectedTheme.badge['red'].background}; + color: ${(props) => props.theme.colors.selectedTheme.badge.red.text}; + background: ${(props) => props.theme.colors.selectedTheme.badge.red.background}; min-width: 100px; } .badge-yellow { - color: ${(props) => props.theme.colors.selectedTheme.badge['yellow'].text}; - background: ${(props) => props.theme.colors.selectedTheme.badge['yellow'].background}; + color: ${(props) => props.theme.colors.selectedTheme.badge.yellow.text}; + background: ${(props) => props.theme.colors.selectedTheme.badge.yellow.background}; min-width: 70px; } ${(props) => - css` - border-left: 3px solid - ${props.$isEligible - ? props.theme.colors.selectedTheme.badge.yellow.background - : props.theme.colors.selectedTheme.badge.red.background}; + `border-left: 3px solid + ${ + props.$isEligible + ? props.theme.colors.selectedTheme.badge.yellow.background + : props.theme.colors.selectedTheme.badge.red.background + }; `} `; diff --git a/sections/futures/LeverageInput/LeverageInput.tsx b/sections/futures/LeverageInput/LeverageInput.tsx index c1a2cd1c14..ed0cc687c8 100644 --- a/sections/futures/LeverageInput/LeverageInput.tsx +++ b/sections/futures/LeverageInput/LeverageInput.tsx @@ -1,10 +1,11 @@ import { wei } from '@synthetixio/wei'; -import { FC, useCallback, useMemo, useState } from 'react'; +import { FC, memo, useCallback, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; import styled from 'styled-components'; import Button from 'components/Button'; import CustomNumericInput from 'components/Input/CustomNumericInput'; +import { FlexDivCol, FlexDivRow } from 'components/layout/flex'; import { DEFAULT_FIAT_DECIMALS } from 'constants/defaults'; import { editIsolatedMarginSize } from 'state/futures/actions'; import { setIsolatedMarginLeverageInput } from 'state/futures/reducer'; @@ -18,12 +19,11 @@ import { selectNextPriceDisclaimer, } from 'state/futures/selectors'; import { useAppDispatch, useAppSelector } from 'state/hooks'; -import { FlexDivCol, FlexDivRow } from 'styles/common'; import { floorNumber, truncateNumbers, zeroBN } from 'utils/formatters/number'; import LeverageSlider from '../LeverageSlider'; -const LeverageInput: FC = () => { +const LeverageInput: FC = memo(() => { const { t } = useTranslation(); const dispatch = useAppDispatch(); const [mode, setMode] = useState<'slider' | 'input'>('input'); @@ -131,7 +131,7 @@ const LeverageInput: FC = () => { )} ); -}; +}); const LeverageInputWrapper = styled(FlexDivCol)` margin-bottom: 16px; diff --git a/sections/futures/LeverageSlider/LeverageSlider.tsx b/sections/futures/LeverageSlider/LeverageSlider.tsx index d72eb97f97..9c82dd9adb 100644 --- a/sections/futures/LeverageSlider/LeverageSlider.tsx +++ b/sections/futures/LeverageSlider/LeverageSlider.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import { memo, FC } from 'react'; import { SliderProps } from 'components/Slider/Slider'; import StyledSlider from 'components/Slider/StyledSlider'; @@ -12,34 +12,28 @@ type LeverageSliderProps = SliderProps & { onChangeCommitted?: (event: React.ChangeEvent<{}>, value: number | number[]) => void; }; -const LeverageSlider: React.FC = ({ - minValue, - maxValue, - value, - defaultValue, - disabled, - onChange, - onChangeCommitted, -}) => { - return ( - `${v}x`} - $currentMark={value ?? defaultValue ?? 0} - /> - ); -}; +const LeverageSlider: FC = memo( + ({ minValue, maxValue, value, defaultValue, disabled, onChange, onChangeCommitted }) => { + return ( + `${v}x`} + $currentMark={value ?? defaultValue ?? 0} + /> + ); + } +); export default LeverageSlider; diff --git a/sections/futures/MarketDetails/MarketDetail.tsx b/sections/futures/MarketDetails/MarketDetail.tsx index 9a456c600c..400dfc314a 100644 --- a/sections/futures/MarketDetails/MarketDetail.tsx +++ b/sections/futures/MarketDetails/MarketDetail.tsx @@ -1,8 +1,8 @@ -import { ReactElement } from 'react'; +import { ReactElement, memo, FC } from 'react'; import { useTranslation } from 'react-i18next'; import styled from 'styled-components'; -import StyledTooltip from 'components/Tooltip/StyledTooltip'; +import Tooltip from 'components/Tooltip/Tooltip'; import { selectMarketInfo } from 'state/futures/selectors'; import { useAppSelector } from 'state/hooks'; @@ -15,7 +15,7 @@ type MarketDetailProps = { value: string | ReactElement; }; -const MarketDetail: React.FC = ({ mobile, marketKey, color, value }) => { +const MarketDetail: FC = memo(({ mobile, marketKey, color, value }) => { const { t } = useTranslation(); const marketInfo = useAppSelector(selectMarketInfo); @@ -33,8 +33,6 @@ const MarketDetail: React.FC = ({ mobile, marketKey, color, v return ( @@ -47,8 +45,6 @@ const MarketDetail: React.FC = ({ mobile, marketKey, color, v return ( @@ -58,7 +54,7 @@ const MarketDetail: React.FC = ({ mobile, marketKey, color, v } return children; -}; +}); export default MarketDetail; @@ -67,7 +63,9 @@ const WithCursor = styled.div<{ cursor: 'help' }>` cursor: ${(props) => props.cursor}; `; -const MarketDetailsTooltip = styled(StyledTooltip)<{ mobile?: boolean }>` +const MarketDetailsTooltip = styled(Tooltip).attrs({ position: 'fixed', height: 'auto' })<{ + mobile?: boolean; +}>` z-index: 2; padding: 10px; right: ${(props) => props.mobile && '1px'}; diff --git a/sections/futures/MarketDetails/MarketDetails.tsx b/sections/futures/MarketDetails/MarketDetails.tsx index 28d6c1e900..4357b86422 100644 --- a/sections/futures/MarketDetails/MarketDetails.tsx +++ b/sections/futures/MarketDetails/MarketDetails.tsx @@ -2,9 +2,9 @@ import React from 'react'; import { useTranslation } from 'react-i18next'; import styled, { css } from 'styled-components'; +import { FlexDivCentered } from 'components/layout/flex'; import { selectMarketAsset } from 'state/futures/selectors'; import { useAppSelector } from 'state/hooks'; -import { FlexDivCentered } from 'styles/common'; import media from 'styles/media'; import MarketsDropdown from '../Trade/MarketsDropdown'; diff --git a/sections/futures/MarketInfo/MarketHead.tsx b/sections/futures/MarketInfo/MarketHead.tsx index d312688899..6dce43c6bb 100644 --- a/sections/futures/MarketInfo/MarketHead.tsx +++ b/sections/futures/MarketInfo/MarketHead.tsx @@ -1,17 +1,15 @@ import Head from 'next/head'; -import React from 'react'; +import { FC } from 'react'; import { useTranslation } from 'react-i18next'; import { DEFAULT_CRYPTO_DECIMALS } from 'constants/defaults'; -import useSelectedPriceCurrency from 'hooks/useSelectedPriceCurrency'; import { selectMarketAsset, selectSkewAdjustedPrice } from 'state/futures/selectors'; import { useAppSelector } from 'state/hooks'; import { formatCurrency } from 'utils/formatters/number'; import { getDisplayAsset, isDecimalFour } from 'utils/futures'; -const MarketHead: React.FC = () => { +const MarketHead: FC = () => { const { t } = useTranslation(); - const { selectedPriceCurrency } = useSelectedPriceCurrency(); const marketAsset = useAppSelector(selectMarketAsset); const latestPrice = useAppSelector(selectSkewAdjustedPrice); @@ -23,8 +21,8 @@ const MarketHead: React.FC = () => { {latestPrice ? t('futures.market.page-title-rate', { marketName, - rate: formatCurrency(selectedPriceCurrency.name, latestPrice, { - currencyKey: selectedPriceCurrency.name, + rate: formatCurrency('sUSD', latestPrice, { + currencyKey: 'sUSD', minDecimals: marketName != null && isDecimalFour(marketName) ? DEFAULT_CRYPTO_DECIMALS diff --git a/sections/futures/MarketInfoBox/MarketInfoBox.tsx b/sections/futures/MarketInfoBox/MarketInfoBox.tsx index 043981a7dc..0b2457f1d8 100644 --- a/sections/futures/MarketInfoBox/MarketInfoBox.tsx +++ b/sections/futures/MarketInfoBox/MarketInfoBox.tsx @@ -45,17 +45,13 @@ const MarketInfoBox: React.FC = () => { }, [commitDeposit, marketInfo?.keeperDeposit]); const getPotentialAvailableMargin = useCallback( - (trade: FuturesPotentialTradeDetails | null, marketMaxLeverage: Wei | undefined) => { - let inaccessible; - - inaccessible = + (trade: FuturesPotentialTradeDetails | null, marketMaxLeverage?: Wei) => { + let inaccessible = (marketMaxLeverage && trade?.notionalValue.div(marketMaxLeverage).abs()) ?? zeroBN; // If the user has a position open, we'll enforce a min initial margin requirement. - if (inaccessible.gt(0)) { - if (inaccessible.lt(minInitialMargin)) { - inaccessible = minInitialMargin; - } + if (inaccessible.gt(0) && inaccessible.lt(minInitialMargin)) { + inaccessible = minInitialMargin; } // check if available margin will be less than 0 @@ -107,9 +103,7 @@ const MarketInfoBox: React.FC = () => { dataTestId="market-info-box" details={{ 'Available Margin': { - value: `${formatDollars(availableMargin, { - currencyKey: undefined, - })}`, + value: formatDollars(availableMargin, { currencyKey: undefined }), valueNode: ( {formatDollars(previewTradeData?.availableMargin)} @@ -117,9 +111,7 @@ const MarketInfoBox: React.FC = () => { ), }, 'Buying Power': { - value: `${formatDollars(buyingPower, { - currencyKey: undefined, - })}`, + value: formatDollars(buyingPower, { currencyKey: undefined }), valueNode: previewTradeData?.buyingPower && ( {formatDollars(previewTradeData?.buyingPower)} @@ -127,7 +119,7 @@ const MarketInfoBox: React.FC = () => { ), }, 'Margin Usage': { - value: `${formatPercent(marginUsage)}`, + value: formatPercent(marginUsage), valueNode: ( {formatPercent(previewTradeData?.marginUsage)} diff --git a/sections/futures/MobileTrade/OverviewTabs/AccountTab.tsx b/sections/futures/MobileTrade/OverviewTabs/AccountTab.tsx index 5ccf78e6c9..159005e076 100644 --- a/sections/futures/MobileTrade/OverviewTabs/AccountTab.tsx +++ b/sections/futures/MobileTrade/OverviewTabs/AccountTab.tsx @@ -1,13 +1,12 @@ import React from 'react'; +import { Pane, SectionHeader, SectionTitle } from 'sections/futures/mobile'; import MarketInfoBox from 'sections/futures/MarketInfoBox'; import MarketActions from 'sections/futures/Trade/MarketActions'; import MarginInfoBox from 'sections/futures/TradeCrossMargin/CrossMarginInfoBox'; import { selectFuturesType } from 'state/futures/selectors'; import { useAppSelector } from 'state/hooks'; -import { Pane, SectionHeader, SectionTitle } from '../common'; - const AccountTab: React.FC = () => { const accountType = useAppSelector(selectFuturesType); return ( diff --git a/sections/futures/MobileTrade/OverviewTabs/PriceTab.tsx b/sections/futures/MobileTrade/OverviewTabs/PriceTab.tsx index cd8c6309d3..c683ef75f1 100644 --- a/sections/futures/MobileTrade/OverviewTabs/PriceTab.tsx +++ b/sections/futures/MobileTrade/OverviewTabs/PriceTab.tsx @@ -1,10 +1,9 @@ import React from 'react'; import styled from 'styled-components'; +import { Pane } from 'sections/futures/mobile'; import PositionChart from 'sections/futures/PositionChart'; -import { Pane } from '../common'; - const PriceTab: React.FC = () => { return ( diff --git a/sections/futures/MobileTrade/OverviewTabs/StatsTab.tsx b/sections/futures/MobileTrade/OverviewTabs/StatsTab.tsx index 1dc484b124..f06c0b5c01 100644 --- a/sections/futures/MobileTrade/OverviewTabs/StatsTab.tsx +++ b/sections/futures/MobileTrade/OverviewTabs/StatsTab.tsx @@ -1,9 +1,8 @@ import React from 'react'; +import { Pane, SectionHeader, SectionTitle } from 'sections/futures/mobile'; import MarketDetails from 'sections/futures/MarketDetails'; -import { Pane, SectionHeader, SectionTitle } from '../common'; - const StatsTab: React.FC = () => { return ( diff --git a/sections/futures/MobileTrade/OverviewTabs/TradesTab.tsx b/sections/futures/MobileTrade/OverviewTabs/TradesTab.tsx index 6338a56be9..c1210f559c 100644 --- a/sections/futures/MobileTrade/OverviewTabs/TradesTab.tsx +++ b/sections/futures/MobileTrade/OverviewTabs/TradesTab.tsx @@ -1,9 +1,8 @@ import React from 'react'; +import { Pane } from 'sections/futures/mobile'; import TradesHistoryTable from 'sections/futures/TradingHistory/TradesHistoryTable'; -import { Pane } from '../common'; - const TradesTab: React.FC = () => { return ( diff --git a/sections/futures/MobileTrade/PositionDetails.tsx b/sections/futures/MobileTrade/PositionDetails.tsx index b72f52f6fc..81e78630f4 100644 --- a/sections/futures/MobileTrade/PositionDetails.tsx +++ b/sections/futures/MobileTrade/PositionDetails.tsx @@ -1,11 +1,11 @@ import React from 'react'; import styled from 'styled-components'; +import { SectionHeader, SectionSeparator, SectionTitle } from 'sections/futures/mobile'; import { selectPosition } from 'state/futures/selectors'; import { useAppSelector } from 'state/hooks'; import PositionCard from '../PositionCard'; -import { SectionHeader, SectionSeparator, SectionTitle } from './common'; const PositionDetails = () => { const position = useAppSelector(selectPosition); diff --git a/sections/futures/MobileTrade/UserTabs/OrdersTab.tsx b/sections/futures/MobileTrade/UserTabs/OrdersTab.tsx index fa3d3752c8..3de262961c 100644 --- a/sections/futures/MobileTrade/UserTabs/OrdersTab.tsx +++ b/sections/futures/MobileTrade/UserTabs/OrdersTab.tsx @@ -1,9 +1,8 @@ import React from 'react'; +import { SectionHeader, SectionTitle } from 'sections/futures/mobile'; import OpenOrdersTable from 'sections/futures/UserInfo/OpenOrdersTable'; -import { SectionHeader, SectionTitle } from '../common'; - const OrdersTab: React.FC = () => { return (
diff --git a/sections/futures/MobileTrade/UserTabs/TradesTab.tsx b/sections/futures/MobileTrade/UserTabs/TradesTab.tsx index d960215d6c..00f9712d6b 100644 --- a/sections/futures/MobileTrade/UserTabs/TradesTab.tsx +++ b/sections/futures/MobileTrade/UserTabs/TradesTab.tsx @@ -4,20 +4,20 @@ import { useTranslation } from 'react-i18next'; import { CellProps } from 'react-table'; import styled, { css } from 'styled-components'; -import Table, { TableNoResults } from 'components/Table'; +import { GridDivCenteredRow } from 'components/layout/grid'; +import Table, { TableHeader, TableNoResults } from 'components/Table'; import { ETH_UNIT } from 'constants/network'; import Connector from 'containers/Connector'; import { FuturesTrade } from 'queries/futures/types'; import useGetFuturesTradesForAccount from 'queries/futures/useGetFuturesTradesForAccount'; +import { SectionHeader, SectionTitle } from 'sections/futures/mobile'; import TimeDisplay from 'sections/futures/Trades/TimeDisplay'; import { PositionSide, TradeStatus } from 'sections/futures/types'; import { selectMarketAsset } from 'state/futures/selectors'; import { useAppSelector } from 'state/hooks'; -import { GridDivCenteredRow } from 'styles/common'; import { formatCryptoCurrency } from 'utils/formatters/number'; import { FuturesMarketAsset, getMarketName } from 'utils/futures'; -import { SectionHeader, SectionTitle } from '../common'; import TradeDrawer from '../drawers/TradeDrawer'; const TradesTab: React.FC = () => { @@ -64,24 +64,18 @@ const TradesTab: React.FC = () => { }} columns={[ { - Header: ( - {t('futures.market.user.trades.table.date')} - ), + Header: {t('futures.market.user.trades.table.date')}, accessor: 'timestamp', Cell: (cellProps: CellProps) => ( - + ), width: 70, sortable: true, }, { - Header: ( - - {t('futures.market.user.trades.table.side-type')} - - ), + Header: {t('futures.market.user.trades.table.side-type')}, accessor: 'side', sortType: 'basic', Cell: (cellProps: CellProps) => ( @@ -94,11 +88,7 @@ const TradesTab: React.FC = () => { sortable: true, }, { - Header: ( - - {t('futures.market.user.trades.table.trade-size')} - - ), + Header: {t('futures.market.user.trades.table.trade-size')}, accessor: 'size', sortType: 'basic', Cell: (cellProps: CellProps) => ( @@ -127,11 +117,6 @@ const TradesTab: React.FC = () => { export default TradesTab; -const StyledTableHeader = styled.div` - font-family: ${(props) => props.theme.fonts.regular}; - text-transform: capitalize; -`; - const StyledPositionSide = styled.div<{ side: PositionSide }>` text-transform: uppercase; font-weight: bold; diff --git a/sections/futures/MobileTrade/UserTabs/TransfersTab.tsx b/sections/futures/MobileTrade/UserTabs/TransfersTab.tsx index c87a6fd0fe..52aac25cae 100644 --- a/sections/futures/MobileTrade/UserTabs/TransfersTab.tsx +++ b/sections/futures/MobileTrade/UserTabs/TransfersTab.tsx @@ -2,18 +2,16 @@ import React from 'react'; import { useTranslation } from 'react-i18next'; import styled from 'styled-components'; -import Table, { TableNoResults } from 'components/Table'; +import Table, { TableHeader, TableNoResults } from 'components/Table'; import useGetFuturesMarginTransfers from 'queries/futures/useGetFuturesMarginTransfers'; +import { SectionHeader, SectionTitle } from 'sections/futures/mobile'; import { timePresentation } from 'utils/formatters/date'; -import { SectionHeader, SectionTitle } from '../common'; - const TransfersTab: React.FC = () => { const marginTransfersQuery = useGetFuturesMarginTransfers(); - const marginTransfers = React.useMemo( - () => (marginTransfersQuery.isSuccess ? marginTransfersQuery?.data ?? [] : []), - [marginTransfersQuery.isSuccess, marginTransfersQuery.data] - ); + const marginTransfers = React.useMemo(() => marginTransfersQuery?.data ?? [], [ + marginTransfersQuery.data, + ]); const { isLoading, isFetched: isLoaded } = marginTransfersQuery; @@ -30,21 +28,13 @@ const TransfersTab: React.FC = () => { highlightRowsOnHover columns={[ { - Header: ( - - {t('futures.market.user.transfers.table.action')} - - ), + Header: {t('futures.market.user.transfers.table.action')}, accessor: 'action', Cell: (cellProps: any) => {cellProps.value}, width: 50, }, { - Header: ( - - {t('futures.market.user.transfers.table.amount')} - - ), + Header: {t('futures.market.user.transfers.table.amount')}, accessor: 'amount', sortType: 'basic', Cell: (cellProps: any) => ( @@ -56,9 +46,7 @@ const TransfersTab: React.FC = () => { width: 50, }, { - Header: ( - {t('futures.market.user.transfers.table.date')} - ), + Header: {t('futures.market.user.transfers.table.date')}, accessor: 'timestamp', Cell: (cellProps: any) => ( {timePresentation(cellProps.value, t)} @@ -104,9 +92,4 @@ const StyledAmountCell = styled(DefaultCell)<{ isPositive: boolean }>` : props.theme.colors.selectedTheme.red}; `; -const StyledTableHeader = styled.div` - font-family: ${(props) => props.theme.fonts.regular}; - text-transform: capitalize; -`; - export default TransfersTab; diff --git a/sections/futures/MobileTrade/drawers/TradeDrawer.tsx b/sections/futures/MobileTrade/drawers/TradeDrawer.tsx index bdf0b9e58c..4088cc0334 100644 --- a/sections/futures/MobileTrade/drawers/TradeDrawer.tsx +++ b/sections/futures/MobileTrade/drawers/TradeDrawer.tsx @@ -38,7 +38,7 @@ const TradeDrawer: React.FC = ({ trade, closeDrawer }) => { label: 'Price', value: formatDollars(trade.price), }, - { label: 'Date/Time', value: }, + { label: 'Date/Time', value: }, { label: 'PnL', value: trade.pnl.eq(0) ? ( diff --git a/sections/futures/OrderPriceInput/OrderPriceInput.tsx b/sections/futures/OrderPriceInput/OrderPriceInput.tsx index 3fdfa47866..40c41bd339 100644 --- a/sections/futures/OrderPriceInput/OrderPriceInput.tsx +++ b/sections/futures/OrderPriceInput/OrderPriceInput.tsx @@ -8,7 +8,7 @@ import styled from 'styled-components'; import CustomInput from 'components/Input/CustomInput'; import InputTitle from 'components/Input/InputTitle'; import SegmentedControl from 'components/SegmentedControl'; -import StyledTooltip from 'components/Tooltip/StyledTooltip'; +import Tooltip from 'components/Tooltip/Tooltip'; import { FuturesOrderType } from 'queries/futures/types'; import { selectMarketPrice, selectMarketInfo, selectLeverageSide } from 'state/futures/selectors'; import { useAppSelector } from 'state/hooks'; @@ -96,13 +96,13 @@ export default function OrderPriceInput({ invalid={!!minMaxLabelString} dataTestId="order-price-input" disabled={isDisabled} - right={'sUSD'} + right="sUSD" value={localValue} placeholder="0.0" onChange={handleOnChange} /> - {t('futures.market.trade.orders.fee-rejection-label')}: - + { setPercent(value); diff --git a/sections/futures/OrderSizing/OrderSizing.tsx b/sections/futures/OrderSizing/OrderSizing.tsx index 9151d91dd1..723a33b363 100644 --- a/sections/futures/OrderSizing/OrderSizing.tsx +++ b/sections/futures/OrderSizing/OrderSizing.tsx @@ -1,10 +1,11 @@ import { wei } from '@synthetixio/wei'; -import React, { ChangeEvent, useMemo, useState } from 'react'; +import React, { ChangeEvent, useMemo, useState, memo } from 'react'; import styled from 'styled-components'; import SwitchAssetArrows from 'assets/svg/futures/switch-arrows.svg'; import CustomInput from 'components/Input/CustomInput'; import InputTitle from 'components/Input/InputTitle'; +import { FlexDivRow } from 'components/layout/flex'; import { useFuturesContext } from 'contexts/FuturesContext'; import { editTradeSizeInput } from 'state/futures/actions'; import { @@ -19,7 +20,6 @@ import { selectMarketAsset, } from 'state/futures/selectors'; import { useAppDispatch, useAppSelector } from 'state/hooks'; -import { FlexDivRow } from 'styles/common'; import { floorNumber, isZero, zeroBN } from 'utils/formatters/number'; import { getDisplayAsset } from 'utils/futures'; @@ -30,7 +30,7 @@ type OrderSizingProps = { disabled?: boolean; }; -const OrderSizing: React.FC = ({ disabled, isMobile }) => { +const OrderSizing: React.FC = memo(({ disabled, isMobile }) => { const { maxUsdInputAmount } = useFuturesContext(); const dispatch = useAppDispatch(); @@ -133,7 +133,7 @@ const OrderSizing: React.FC = ({ disabled, isMobile }) => { {selectedAccountType === 'cross_margin' && } ); -}; +}); const OrderSizingContainer = styled.div` margin-top: 28px; diff --git a/sections/futures/PositionButtons/PositionButtons.tsx b/sections/futures/PositionButtons/PositionButtons.tsx index 42c9e25509..fd67661d15 100644 --- a/sections/futures/PositionButtons/PositionButtons.tsx +++ b/sections/futures/PositionButtons/PositionButtons.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import { memo, FC } from 'react'; import styled, { css } from 'styled-components'; import Button from 'components/Button'; @@ -13,7 +13,7 @@ interface PositionButtonsProps { type?: 'button' | 'submit' | 'reset' | undefined; } -const PositionButtons: React.FC = ({ selected, onSelect }) => { +const PositionButtons: FC = memo(({ selected, onSelect }) => { const marketInfo = useAppSelector(selectMarketInfo); return ( @@ -40,7 +40,7 @@ const PositionButtons: React.FC = ({ selected, onSelect }) ); -}; +}); type PositionButtonProps = { $position: PositionSide; @@ -74,7 +74,7 @@ const StyledPositionButton = styled(Button)` color: ${props.theme.colors.selectedTheme.green}; ${props.$isActive && css` - border: 1px solid ${(props) => props.theme.colors.selectedTheme.green}; + border: 1px solid ${props.theme.colors.selectedTheme.green}; border-radius: 8px; background: linear-gradient( 180deg, diff --git a/sections/futures/PositionCard/ClosePositionModal.tsx b/sections/futures/PositionCard/ClosePositionModal.tsx index 1987934d5a..6b517f4d8a 100644 --- a/sections/futures/PositionCard/ClosePositionModal.tsx +++ b/sections/futures/PositionCard/ClosePositionModal.tsx @@ -5,15 +5,16 @@ import styled from 'styled-components'; import BaseModal from 'components/BaseModal'; import Button from 'components/Button'; -import Error from 'components/Error'; +import Error from 'components/ErrorView'; +import { FlexDivCentered, FlexDivCol } from 'components/layout/flex'; import { ButtonLoader } from 'components/Loader/Loader'; import Connector from 'containers/Connector'; import { getFuturesMarketContract } from 'queries/futures/utils'; import { FuturesFilledPosition } from 'sdk/types/futures'; import { selectIsClosingPosition, selectMarketAsset } from 'state/futures/selectors'; import { useAppSelector } from 'state/hooks'; -import { FlexDivCentered, FlexDivCol } from 'styles/common'; import { formatCurrency, formatDollars, formatNumber, zeroBN } from 'utils/formatters/number'; +import logError from 'utils/logError'; import { PositionSide } from '../types'; @@ -53,9 +54,7 @@ function ClosePositionModal({ const orderFee = await FuturesMarketContract.orderFee(size.toBN()); setOrderFee(wei(orderFee.fee)); } catch (e) { - // @ts-ignore logError(e.message); - // @ts-ignore setError(e?.data?.message ?? e.message); } }; diff --git a/sections/futures/PositionCard/PositionCard.tsx b/sections/futures/PositionCard/PositionCard.tsx index c4daa23a1d..7c56bd0739 100644 --- a/sections/futures/PositionCard/PositionCard.tsx +++ b/sections/futures/PositionCard/PositionCard.tsx @@ -3,8 +3,10 @@ import React, { useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; import styled, { css } from 'styled-components'; +import { FlexDivCentered, FlexDivCol } from 'components/layout/flex'; import PreviewArrow from 'components/PreviewArrow'; -import StyledTooltip from 'components/Tooltip/StyledTooltip'; +import { Body } from 'components/Text'; +import Tooltip from 'components/Tooltip/Tooltip'; import { DEFAULT_CRYPTO_DECIMALS } from 'constants/defaults'; import { NO_VALUE } from 'constants/placeholder'; import Connector from 'containers/Connector'; @@ -22,7 +24,7 @@ import { selectActivePositionHistory, } from 'state/futures/selectors'; import { useAppSelector } from 'state/hooks'; -import { FlexDivCentered, FlexDivCol, PillButtonDiv } from 'styles/common'; +import { PillButtonDiv } from 'styles/common'; import media from 'styles/media'; import { isFiatCurrency } from 'utils/currencies'; import { formatDollars, formatPercent, zeroBN } from 'utils/formatters/number'; @@ -138,10 +140,7 @@ const PositionCard: React.FC = () => { marketLongName: getSynthDescription(marketAsset, synthsMap, t), marketPrice: ( <> - {`${formatDollars(marketPrice, { - minDecimals, - isAssetPrice: true, - })}`} + {formatDollars(marketPrice, { minDecimals, isAssetPrice: true })} { {formatDollars(previewData.fillPrice ?? zeroBN, { @@ -289,30 +288,22 @@ const PositionCard: React.FC = () => { - {data.marketShortName} + {data.marketShortName} {data.marketPrice} - - + + {t('futures.market.position-card.position-side')} - +
{data.positionSide}
- - + + {t('futures.market.position-card.position-size')} - + {data.positionSize} @@ -320,14 +311,10 @@ const PositionCard: React.FC = () => { - - + + {t('futures.market.position-card.net-funding')} - + {positionDetails ? ( = () => { )} - - - {t('futures.market.position-card.u-pnl')} - + + {t('futures.market.position-card.u-pnl')} {positionDetails ? ( zeroBN ? 'green' : data.pnl < zeroBN ? 'red' : ''}> @@ -360,14 +341,8 @@ const PositionCard: React.FC = () => { )} - - - {t('futures.market.position-card.r-pnl')} - + + {t('futures.market.position-card.r-pnl')} {positionDetails ? ( = () => { - - - {t('futures.market.position-card.leverage')} - + + {t('futures.market.position-card.leverage')} {data.leverage} @@ -403,25 +372,21 @@ const PositionCard: React.FC = () => { - + {t('futures.market.position-card.liquidation-price')} - + {data.liquidationPrice} - + {t('futures.market.position-card.avg-entry-price')} - + {data.avgEntryPrice} @@ -430,6 +395,7 @@ const PositionCard: React.FC = () => { ); }; + export default PositionCard; const Container = styled.div` @@ -482,33 +448,24 @@ const InfoRow = styled.div` } `; -const StyledSubtitle = styled.p` - font-family: ${(props) => props.theme.fonts.regular}; +const Subtitle = styled(Body)` font-size: 13px; color: ${(props) => props.theme.colors.selectedTheme.gray}; text-transform: capitalize; - margin: 0; `; -const StyledSubtitleWithCursor = styled.p` - font-family: ${(props) => props.theme.fonts.regular}; - font-size: 13px; - color: ${(props) => props.theme.colors.selectedTheme.gray}; - text-transform: capitalize; - margin: 0; +const SubtitleWithCursor = styled(Subtitle)` cursor: help; `; -const PositionCardTooltip = styled(StyledTooltip)` +const PositionCardTooltip = styled(Tooltip).attrs({ preset: 'fixed', height: 'auto' })` z-index: 2; padding: 0px 10px 0px 10px; `; -const StyledValue = styled.p` - font-family: ${(props) => props.theme.fonts.mono}; +const StyledValue = styled(Body).attrs({ mono: true })` font-size: 13px; color: ${(props) => props.theme.colors.selectedTheme.button.text.primary}; - margin: 0; text-align: end; ${Container}#closed & { color: ${(props) => props.theme.colors.selectedTheme.gray}; diff --git a/sections/futures/PositionChart/PositionChart.tsx b/sections/futures/PositionChart/PositionChart.tsx index c12da9ac81..2d7f342f3f 100644 --- a/sections/futures/PositionChart/PositionChart.tsx +++ b/sections/futures/PositionChart/PositionChart.tsx @@ -44,8 +44,8 @@ export default function PositionChart() { }, [subgraphPosition, position]); const onToggleLines = useCallback(() => { - setShowOrderLines(!showOrderLines); - }, [setShowOrderLines, showOrderLines]); + setShowOrderLines((show) => !show); + }, [setShowOrderLines]); return ( diff --git a/sections/futures/ShareModal/AmountContainer.tsx b/sections/futures/ShareModal/AmountContainer.tsx index c75a0d531b..49f1df45c5 100644 --- a/sections/futures/ShareModal/AmountContainer.tsx +++ b/sections/futures/ShareModal/AmountContainer.tsx @@ -1,4 +1,4 @@ -import { FC } from 'react'; +import { FC, useMemo } from 'react'; import styled from 'styled-components'; import CurrencyIcon from 'components/Currency/CurrencyIcon'; @@ -14,12 +14,6 @@ type AmountContainerProps = { position: FuturesPosition | null | undefined; }; -const currencyIconStyle = { - height: '1.94vw', - width: 'auto', - margin: '-0.3vw 0.5vw 0vw 0vw', -}; - const AmountContainer: FC = ({ position }) => { const marketAsset = useAppSelector(selectMarketAsset); @@ -29,7 +23,7 @@ const AmountContainer: FC = ({ position }) => { const side = positionDetails?.side === 'long' ? PositionSide.LONG : PositionSide.SHORT; const pnlPct = positionDetails?.pnlPct.mul(100); - const amount = () => { + const amount = useMemo(() => { if (pnlPct) { return pnlPct.gt(0) ? `+${pnlPct.toNumber().toFixed(2)}%` @@ -37,30 +31,33 @@ const AmountContainer: FC = ({ position }) => { ? `+0.00%` : `${pnlPct.toNumber().toFixed(2)}%`; } - }; + }, [pnlPct]); return ( - <> - - - - {marketName} - {`|`} - {side.toUpperCase()} - {`|`} - {`${leverage}`} - - {amount()} - - + + + + {marketName} + | + {side.toUpperCase()} + | + {leverage} + + {amount} + ); }; +const StyledCurrencyIcon = styled(CurrencyIcon)` + height: 1.94vw; + width: auto; + margin: -0.3vw 0.5vw 0vw 0vw; +`; + const StyledPositionLeverage = styled.div` display: flex; flex-direction: column; color: ${(props) => props.theme.colors.common.primaryGold}; - font-size: 1.07vw; `; diff --git a/sections/futures/Trade/DelayedOrderConfirmationModal.tsx b/sections/futures/Trade/DelayedOrderConfirmationModal.tsx index 64839ee32e..1bd26dad5e 100644 --- a/sections/futures/Trade/DelayedOrderConfirmationModal.tsx +++ b/sections/futures/Trade/DelayedOrderConfirmationModal.tsx @@ -4,7 +4,8 @@ import styled from 'styled-components'; import BaseModal from 'components/BaseModal'; import Button from 'components/Button'; -import Error from 'components/Error'; +import Error from 'components/ErrorView'; +import { FlexDivCentered } from 'components/layout/flex'; import { ButtonLoader } from 'components/Loader/Loader'; import { DesktopOnlyView, MobileOrTabletView } from 'components/Media'; import useSelectedPriceCurrency from 'hooks/useSelectedPriceCurrency'; @@ -27,7 +28,6 @@ import { } from 'state/futures/selectors'; import { useAppDispatch, useAppSelector } from 'state/hooks'; import { FetchStatus } from 'state/types'; -import { FlexDivCentered } from 'styles/common'; import { getKnownError } from 'utils/formatters/error'; import { zeroBN, @@ -165,7 +165,7 @@ const DelayedOrderConfirmationModal: FC = () => { dispatch(setOpenModal(null)); }, [dispatch]); - const handleConfirmOrder = async () => { + const handleConfirmOrder = () => { dispatch( modifyIsolatedPosition({ sizeDelta: nativeSizeDelta, @@ -191,7 +191,7 @@ const DelayedOrderConfirmationModal: FC = () => { - {row.value} + {row.value} ))} diff --git a/sections/futures/Trade/FuturesUnsupported.tsx b/sections/futures/Trade/FuturesUnsupported.tsx index 538271d1f1..68a20cee46 100644 --- a/sections/futures/Trade/FuturesUnsupported.tsx +++ b/sections/futures/Trade/FuturesUnsupported.tsx @@ -10,12 +10,10 @@ const FuturesUnsupportedNetwork = () => { return ( {t('futures.page-title')} - <> - {t('common.l2-cta')} - -
{t('homepage.l2.cta-buttons.switch-l2')}
-
- + {t('common.l2-cta')} + +
{t('homepage.l2.cta-buttons.switch-l2')}
+
); }; diff --git a/sections/futures/Trade/ManagePosition.tsx b/sections/futures/Trade/ManagePosition.tsx index 22940e64df..ae8c5ac462 100644 --- a/sections/futures/Trade/ManagePosition.tsx +++ b/sections/futures/Trade/ManagePosition.tsx @@ -3,7 +3,7 @@ import { useTranslation } from 'react-i18next'; import styled from 'styled-components'; import Button from 'components/Button'; -import Error from 'components/Error'; +import Error from 'components/ErrorView'; import { useFuturesContext } from 'contexts/FuturesContext'; import { previewErrorI18n } from 'queries/futures/constants'; import { PositionSide } from 'sdk/types/futures'; @@ -86,11 +86,14 @@ const ManagePosition: React.FC = () => { const leverageValid = useMemo(() => { if (selectedAccountType === 'cross_margin') return true; - const leverageNum = Number(leverage || 0); - return leverageNum > 0 && leverageNum < maxLeverageValue.toNumber(); + return leverage.gt(0) && leverage.lt(maxLeverageValue); }, [selectedAccountType, maxLeverageValue, leverage]); const placeOrderDisabledReason = useMemo(() => { + if (!leverageValid) return 'invalid_leverage'; + if (marketInfo?.isSuspended) return 'market_suspended'; + if (isMarketCapReached) return 'market_cap_reached'; + const invalidReason = orderPriceInvalidLabel( orderPrice, leverageSide, @@ -98,9 +101,6 @@ const ManagePosition: React.FC = () => { orderType ); - if (!leverageValid) return 'invalid_leverage'; - if (marketInfo?.isSuspended) return 'market_suspended'; - if (isMarketCapReached) return 'market_cap_reached'; if ((orderType === 'limit' || orderType === 'stop market') && !!invalidReason) return invalidReason; if (susdSize.gt(maxUsdInputAmount)) return 'max_size_exceeded'; diff --git a/sections/futures/Trade/MarketsDropdownOption.tsx b/sections/futures/Trade/MarketsDropdownOption.tsx index 1a02591612..a804d35acc 100644 --- a/sections/futures/Trade/MarketsDropdownOption.tsx +++ b/sections/futures/Trade/MarketsDropdownOption.tsx @@ -3,7 +3,7 @@ import styled, { css } from 'styled-components'; import MarketBadge from 'components/Badge/MarketBadge'; import CurrencyIcon from 'components/Currency/CurrencyIcon'; -import { FlexDivCentered } from 'styles/common'; +import { FlexDivCentered } from 'components/layout/flex'; import { MarketsCurrencyOption } from './MarketsDropdown'; import { CurrencyLabel, SingleValueContainer } from './MarketsDropdownSingleValue'; diff --git a/sections/futures/Trade/MarketsDropdownSingleValue.tsx b/sections/futures/Trade/MarketsDropdownSingleValue.tsx index 4a77bb0d4f..ee638b1d1a 100644 --- a/sections/futures/Trade/MarketsDropdownSingleValue.tsx +++ b/sections/futures/Trade/MarketsDropdownSingleValue.tsx @@ -4,7 +4,7 @@ import styled from 'styled-components'; import MarketBadge from 'components/Badge/MarketBadge'; import CurrencyIcon from 'components/Currency/CurrencyIcon'; -import { FlexDivCentered } from 'styles/common'; +import { FlexDivCentered } from 'components/layout/flex'; import { MarketKeyByAsset } from 'utils/futures'; import { MarketsCurrencyOption } from './MarketsDropdown'; diff --git a/sections/futures/Trade/TradeConfirmationModal.tsx b/sections/futures/Trade/TradeConfirmationModal.tsx index ae93dc9c11..a6bd4a337d 100644 --- a/sections/futures/Trade/TradeConfirmationModal.tsx +++ b/sections/futures/Trade/TradeConfirmationModal.tsx @@ -6,7 +6,8 @@ import styled from 'styled-components'; import BaseModal from 'components/BaseModal'; import Button from 'components/Button'; -import ErrorView from 'components/Error'; +import ErrorView from 'components/ErrorView'; +import { FlexDivCentered } from 'components/layout/flex'; import { ButtonLoader } from 'components/Loader/Loader'; import { DesktopOnlyView, MobileOrTabletView } from 'components/Media'; import { MIN_MARGIN_AMOUNT } from 'constants/futures'; @@ -19,7 +20,6 @@ import { selectTradePreview, } from 'state/futures/selectors'; import { useAppSelector } from 'state/hooks'; -import { FlexDivCentered } from 'styles/common'; import { zeroBN, formatCurrency, diff --git a/sections/futures/Trade/TradeIsolatedMargin.tsx b/sections/futures/Trade/TradeIsolatedMargin.tsx index 94ab6140e2..17cffd9c6f 100644 --- a/sections/futures/Trade/TradeIsolatedMargin.tsx +++ b/sections/futures/Trade/TradeIsolatedMargin.tsx @@ -1,7 +1,7 @@ import { useTranslation } from 'react-i18next'; import styled from 'styled-components'; -import Error from 'components/Error'; +import Error from 'components/ErrorView'; import SegmentedControl from 'components/SegmentedControl'; import { DEFAULT_DELAYED_LEVERAGE_CAP, ISOLATED_MARGIN_ORDER_TYPES } from 'constants/futures'; import { setOpenModal } from 'state/app/reducer'; diff --git a/sections/futures/Trade/TransferIsolatedMarginModal.tsx b/sections/futures/Trade/TransferIsolatedMarginModal.tsx index e042788056..85e2f12951 100644 --- a/sections/futures/Trade/TransferIsolatedMarginModal.tsx +++ b/sections/futures/Trade/TransferIsolatedMarginModal.tsx @@ -5,8 +5,9 @@ import styled from 'styled-components'; import BaseModal from 'components/BaseModal'; import Button from 'components/Button'; -import Error from 'components/Error'; +import Error from 'components/ErrorView'; import CustomInput from 'components/Input/CustomInput'; +import { FlexDivRowCentered } from 'components/layout/flex'; import SegmentedControl from 'components/SegmentedControl'; import Spacer from 'components/Spacer'; import { MIN_MARGIN_AMOUNT } from 'constants/futures'; @@ -18,7 +19,6 @@ import { selectPosition, } from 'state/futures/selectors'; import { useAppDispatch, useAppSelector } from 'state/hooks'; -import { FlexDivRowCentered } from 'styles/common'; import { formatDollars, zeroBN } from 'utils/formatters/number'; type Props = { diff --git a/sections/futures/TradeCrossMargin/CreateAccount.tsx b/sections/futures/TradeCrossMargin/CreateAccount.tsx index 5ca9d11552..40fc01cbf2 100644 --- a/sections/futures/TradeCrossMargin/CreateAccount.tsx +++ b/sections/futures/TradeCrossMargin/CreateAccount.tsx @@ -77,5 +77,5 @@ const CreateAccountButton = styled(Button)` const Questions = styled.div` margin-top: 10px; - border-top: ${(props) => `${props.theme.colors.selectedTheme.border}`}; + border-top: ${(props) => props.theme.colors.selectedTheme.border}; `; diff --git a/sections/futures/TradeCrossMargin/CrossMarginInfoBox.tsx b/sections/futures/TradeCrossMargin/CrossMarginInfoBox.tsx index c5ecae4803..ef4a9ca4a2 100644 --- a/sections/futures/TradeCrossMargin/CrossMarginInfoBox.tsx +++ b/sections/futures/TradeCrossMargin/CrossMarginInfoBox.tsx @@ -4,7 +4,6 @@ import styled from 'styled-components'; import WithdrawArrow from 'assets/svg/futures/withdraw-arrow.svg'; import InfoBox from 'components/InfoBox'; -import { MiniLoader } from 'components/Loader'; import PreviewArrow from 'components/PreviewArrow'; import { useFuturesContext } from 'contexts/FuturesContext'; import { FuturesPotentialTradeDetails } from 'sdk/types/futures'; @@ -152,8 +151,9 @@ function MarginInfoBox({ editingLeverage }: Props) { - {isLoading ? : formatDollars(previewTradeData.freeAccountMargin)} + {formatDollars(previewTradeData.freeAccountMargin)} ), } @@ -161,16 +161,16 @@ function MarginInfoBox({ editingLeverage }: Props) { 'Market Margin': { value: formatDollars(position?.remainingMargin || 0), valueNode: ( - - {isLoading ? : formatDollars(previewTradeData.totalMargin)} + + {formatDollars(previewTradeData.totalMargin)} ), }, 'Margin Usage': { value: formatPercent(marginUsage), valueNode: ( - - {isLoading ? : formatPercent(previewTradeData?.marginUsage)} + + {formatPercent(previewTradeData?.marginUsage)} ), }, @@ -209,8 +209,8 @@ function MarginInfoBox({ editingLeverage }: Props) { ), valueNode: ( - - {isLoading ? : formatNumber(previewTradeData.leverage || 0) + 'x'} + + {formatNumber(previewTradeData.leverage || 0) + 'x'} ), }, diff --git a/sections/futures/TradeCrossMargin/DepositWithdrawCrossMargin.tsx b/sections/futures/TradeCrossMargin/DepositWithdrawCrossMargin.tsx index 871b836193..776591355a 100644 --- a/sections/futures/TradeCrossMargin/DepositWithdrawCrossMargin.tsx +++ b/sections/futures/TradeCrossMargin/DepositWithdrawCrossMargin.tsx @@ -5,8 +5,9 @@ import styled from 'styled-components'; import BaseModal from 'components/BaseModal'; import Button from 'components/Button'; -import ErrorView from 'components/Error'; +import ErrorView from 'components/ErrorView'; import CustomInput from 'components/Input/CustomInput'; +import { FlexDivRowCentered } from 'components/layout/flex'; import Loader from 'components/Loader'; import SegmentedControl from 'components/SegmentedControl'; import { MIN_MARGIN_AMOUNT } from 'constants/futures'; @@ -19,7 +20,6 @@ import { selectIsSubmittingCrossTransfer, } from 'state/futures/selectors'; import { useAppDispatch, useAppSelector } from 'state/hooks'; -import { FlexDivRowCentered } from 'styles/common'; import { formatDollars, zeroBN } from 'utils/formatters/number'; import logError from 'utils/logError'; diff --git a/sections/futures/TradeCrossMargin/EditCrossMarginLeverageModal.tsx b/sections/futures/TradeCrossMargin/EditCrossMarginLeverageModal.tsx index 21356af7d4..9af3e5c0b0 100644 --- a/sections/futures/TradeCrossMargin/EditCrossMarginLeverageModal.tsx +++ b/sections/futures/TradeCrossMargin/EditCrossMarginLeverageModal.tsx @@ -6,8 +6,9 @@ import styled from 'styled-components'; import BaseModal from 'components/BaseModal'; import Button from 'components/Button'; -import ErrorView from 'components/Error'; +import ErrorView from 'components/ErrorView'; import CustomInput from 'components/Input/CustomInput'; +import { FlexDivRow, FlexDivRowCentered } from 'components/layout/flex'; import Loader from 'components/Loader'; import Spacer from 'components/Spacer'; import { NumberSpan } from 'components/Text/NumberLabel'; @@ -33,7 +34,6 @@ import { selectTradePreviewError, } from 'state/futures/selectors'; import { useAppSelector, useAppDispatch } from 'state/hooks'; -import { FlexDivRow, FlexDivRowCentered } from 'styles/common'; import { isUserDeniedError } from 'utils/formatters/error'; import { formatDollars, zeroBN } from 'utils/formatters/number'; import logError from 'utils/logError'; diff --git a/sections/futures/TradeCrossMargin/ManageKeeperBalanceModal.tsx b/sections/futures/TradeCrossMargin/ManageKeeperBalanceModal.tsx index efad7164b3..435a01f65d 100644 --- a/sections/futures/TradeCrossMargin/ManageKeeperBalanceModal.tsx +++ b/sections/futures/TradeCrossMargin/ManageKeeperBalanceModal.tsx @@ -3,7 +3,7 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; import styled from 'styled-components'; -import ErrorView from 'components/Error'; +import ErrorView from 'components/ErrorView'; import CustomInput from 'components/Input/CustomInput'; import Loader from 'components/Loader'; import SegmentedControl from 'components/SegmentedControl'; diff --git a/sections/futures/Trades/TimeDisplay.tsx b/sections/futures/Trades/TimeDisplay.tsx index af13ca3a22..9710bbaf32 100644 --- a/sections/futures/Trades/TimeDisplay.tsx +++ b/sections/futures/Trades/TimeDisplay.tsx @@ -1,29 +1,31 @@ import { format } from 'date-fns'; -import { FC, useCallback, useState } from 'react'; +import { FC, useCallback, useMemo, useState, memo } from 'react'; import styled, { css } from 'styled-components'; import getLocale from 'utils/formatters/getLocale'; type TimeDisplayProps = { - cellPropsValue: any; + value: any; horizontal?: boolean; }; -const TimeDisplay: FC = ({ cellPropsValue, horizontal }) => { - const [show12hr, setShow12h] = useState(false); +const TimeDisplay: FC = memo(({ value, horizontal }) => { + const [show12hr, setShow12h] = useState(false); const handleOnClick = useCallback(() => { - setShow12h(!show12hr); - }, [show12hr]); + setShow12h((current) => !current); + }, []); - const date = format( - new Date(cellPropsValue), - getLocale().formatLong?.date({ width: 'short' }) ?? 'MM/dd/yy' + const locale = useMemo(() => getLocale(), []); + + const date = useMemo( + () => format(new Date(value), locale.formatLong?.date({ width: 'short' }) ?? 'MM/dd/yy'), + [value, locale] ); - const time12hr = new Date(cellPropsValue).toLocaleTimeString(getLocale().code); - const time24hr = format(new Date(cellPropsValue), 'HH:mm:ss', { - locale: getLocale(), - }); + + const time12hr = useMemo(() => new Date(value).toLocaleTimeString(locale.code), [value, locale]); + + const time24hr = useMemo(() => format(new Date(value), 'HH:mm:ss', { locale }), [value, locale]); return ( @@ -31,7 +33,7 @@ const TimeDisplay: FC = ({ cellPropsValue, horizontal }) => {
{show12hr ? time12hr : time24hr}
); -}; +}); const TimeDisplayContainer = styled.div<{ horizontal?: boolean }>` ${(props) => @@ -42,7 +44,7 @@ const TimeDisplayContainer = styled.div<{ horizontal?: boolean }>` margin-right: 5px; } div:last-child { - color: ${(props) => props.theme.colors.common.secondaryGray}; + color: ${props.theme.colors.common.secondaryGray}; } `} `; diff --git a/sections/futures/Trades/Trades.tsx b/sections/futures/Trades/Trades.tsx index 7aa8d959dc..c8cdb30b60 100644 --- a/sections/futures/Trades/Trades.tsx +++ b/sections/futures/Trades/Trades.tsx @@ -5,14 +5,15 @@ import styled, { css } from 'styled-components'; import LinkIcon from 'assets/svg/app/link-blue.svg'; import Card from 'components/Card'; -import Table, { TableNoResults } from 'components/Table'; +import { GridDivCenteredRow } from 'components/layout/grid'; +import Table, { TableHeader, TableNoResults } from 'components/Table'; import { DEFAULT_CRYPTO_DECIMALS } from 'constants/defaults'; import { ETH_UNIT } from 'constants/network'; import { blockExplorer } from 'containers/Connector/Connector'; import useIsL2 from 'hooks/useIsL2'; import useNetworkSwitcher from 'hooks/useNetworkSwitcher'; import { FuturesTrade } from 'queries/futures/types'; -import { ExternalLink, GridDivCenteredRow } from 'styles/common'; +import { ExternalLink } from 'styles/common'; import { formatCryptoCurrency, formatDollars } from 'utils/formatters/number'; import { PositionSide, TradeStatus } from '../types'; @@ -54,22 +55,18 @@ const Trades: React.FC = ({ history, isLoading, isLoaded, marketAss highlightRowsOnHover columns={[ { - Header: ( - {t('futures.market.user.trades.table.date')} - ), + Header: {t('futures.market.user.trades.table.date')}, accessor: 'time', Cell: (cellProps: CellProps) => ( - + ), width: 90, sortable: true, }, { - Header: ( - {t('futures.market.user.trades.table.side')} - ), + Header: {t('futures.market.user.trades.table.side')}, accessor: 'side', sortType: 'basic', Cell: (cellProps: CellProps) => ( @@ -81,9 +78,7 @@ const Trades: React.FC = ({ history, isLoading, isLoaded, marketAss sortable: true, }, { - Header: ( - {t('futures.market.user.trades.table.price')} - ), + Header: {t('futures.market.user.trades.table.price')}, accessor: 'value', sortType: 'basic', Cell: (cellProps: CellProps) => { @@ -98,11 +93,7 @@ const Trades: React.FC = ({ history, isLoading, isLoaded, marketAss sortable: true, }, { - Header: ( - - {t('futures.market.user.trades.table.trade-size')} - - ), + Header: {t('futures.market.user.trades.table.trade-size')}, accessor: 'amount', sortType: 'basic', Cell: (cellProps: CellProps) => ( @@ -112,9 +103,7 @@ const Trades: React.FC = ({ history, isLoading, isLoaded, marketAss sortable: true, }, { - Header: ( - {t('futures.market.user.trades.table.fees')} - ), + Header: {t('futures.market.user.trades.table.fees')}, sortType: 'basic', accessor: 'feesPaid', Cell: (cellProps: CellProps) => ( @@ -124,11 +113,7 @@ const Trades: React.FC = ({ history, isLoading, isLoaded, marketAss sortable: true, }, { - Header: ( - - {t('futures.market.user.trades.table.order-type')} - - ), + Header: {t('futures.market.user.trades.table.order-type')}, accessor: 'type', sortType: 'basic', Cell: (cellProps: CellProps) => <>{cellProps.value}, @@ -167,11 +152,6 @@ const Trades: React.FC = ({ history, isLoading, isLoaded, marketAss export default Trades; -const StyledTableHeader = styled.div` - font-family: ${(props) => props.theme.fonts.regular}; - text-transform: capitalize; -`; - const StyledPositionSide = styled.div<{ side: PositionSide }>` text-transform: uppercase; ${(props) => diff --git a/sections/futures/TradingHistory/SkewInfo.tsx b/sections/futures/TradingHistory/SkewInfo.tsx index 135760b7ed..98836c1c5f 100644 --- a/sections/futures/TradingHistory/SkewInfo.tsx +++ b/sections/futures/TradingHistory/SkewInfo.tsx @@ -4,7 +4,7 @@ import { useMemo } from 'react'; import { useTranslation } from 'react-i18next'; import styled from 'styled-components'; -import StyledTooltip from 'components/Tooltip/StyledTooltip'; +import Tooltip from 'components/Tooltip/Tooltip'; import { selectMarketAsset, selectMarketInfo } from 'state/futures/selectors'; import { useAppSelector } from 'state/hooks'; import { CapitalizedText, NumericValue } from 'styles/common'; @@ -93,7 +93,7 @@ const WithCursor = styled.div<{ cursor: 'help' }>` cursor: ${(props) => props.cursor}; `; -const SkewTooltip = styled(StyledTooltip)<{ isNumber?: boolean }>` +const SkewTooltip = styled(Tooltip)<{ isNumber?: boolean }>` left: -30px; z-index: 2; padding: 10px; diff --git a/sections/futures/TradingHistory/TradesHistoryTable.tsx b/sections/futures/TradingHistory/TradesHistoryTable.tsx index 1b39c0eb83..5bb3ea020d 100644 --- a/sections/futures/TradingHistory/TradesHistoryTable.tsx +++ b/sections/futures/TradingHistory/TradesHistoryTable.tsx @@ -3,7 +3,7 @@ import { useTranslation } from 'react-i18next'; import { CellProps } from 'react-table'; import styled, { css } from 'styled-components'; -import Table from 'components/Table'; +import Table, { TableHeader } from 'components/Table'; import { DEFAULT_CRYPTO_DECIMALS } from 'constants/defaults'; import { NO_VALUE } from 'constants/placeholder'; import { blockExplorer } from 'containers/Connector/Connector'; @@ -242,11 +242,6 @@ const StyledTable = styled(Table)<{ mobile?: boolean }>` } `; -const TableHeader = styled(CapitalizedText)` - font-size: 13px; - font-family: ${(props) => props.theme.fonts.regular}; -`; - const PriceValue = styled(NumericValue)` font-size: 13px; color: ${(props) => props.theme.colors.selectedTheme.button.text.primary}; diff --git a/sections/futures/Transfers/Transfers.tsx b/sections/futures/Transfers/Transfers.tsx index 439a37ceae..1590a4eaca 100644 --- a/sections/futures/Transfers/Transfers.tsx +++ b/sections/futures/Transfers/Transfers.tsx @@ -2,7 +2,7 @@ import { FC, useMemo } from 'react'; import { useTranslation } from 'react-i18next'; import styled from 'styled-components'; -import Table, { TableNoResults } from 'components/Table'; +import Table, { TableHeader, TableNoResults } from 'components/Table'; import { blockExplorer } from 'containers/Connector/Connector'; import useIsL2 from 'hooks/useIsL2'; import useNetworkSwitcher from 'hooks/useNetworkSwitcher'; @@ -29,17 +29,13 @@ const Transfers: FC = ({ marginTransfers, isLoading, isLoaded }) highlightRowsOnHover columns={[ { - Header: ( - {t('futures.market.user.transfers.table.action')} - ), + Header: {t('futures.market.user.transfers.table.action')}, accessor: 'action', Cell: (cellProps: any) => {cellProps.value}, width: 50, }, { - Header: ( - {t('futures.market.user.transfers.table.amount')} - ), + Header: {t('futures.market.user.transfers.table.amount')}, accessor: 'amount', sortType: 'basic', Cell: (cellProps: any) => ( @@ -51,9 +47,7 @@ const Transfers: FC = ({ marginTransfers, isLoading, isLoaded }) width: 50, }, { - Header: ( - {t('futures.market.user.transfers.table.date')} - ), + Header: {t('futures.market.user.transfers.table.date')}, accessor: 'timestamp', Cell: (cellProps: any) => ( {timePresentation(cellProps.value, t)} @@ -61,11 +55,7 @@ const Transfers: FC = ({ marginTransfers, isLoading, isLoaded }) width: 50, }, { - Header: ( - - {t('futures.market.user.transfers.table.transaction')} - - ), + Header: {t('futures.market.user.transfers.table.transaction')}, accessor: 'txHash', Cell: (cellProps: any) => { return ( @@ -130,8 +120,3 @@ const StyledAmountCell = styled(DefaultCell)<{ isPositive: boolean }>` ? props.theme.colors.selectedTheme.green : props.theme.colors.selectedTheme.red}; `; - -const StyledTableHeader = styled.div` - font-family: ${(props) => props.theme.fonts.regular}; - text-transform: capitalize; -`; diff --git a/sections/futures/UserInfo/OpenOrdersTable.tsx b/sections/futures/UserInfo/OpenOrdersTable.tsx index 6deedbb35b..f82e160a3a 100644 --- a/sections/futures/UserInfo/OpenOrdersTable.tsx +++ b/sections/futures/UserInfo/OpenOrdersTable.tsx @@ -6,7 +6,7 @@ import styled, { css } from 'styled-components'; import Badge from 'components/Badge'; import Currency from 'components/Currency'; import { DesktopOnlyView, MobileOrTabletView } from 'components/Media'; -import Table, { TableNoResults } from 'components/Table'; +import Table, { TableHeader, TableNoResults } from 'components/Table'; import { DEFAULT_DELAYED_EXECUTION_BUFFER } from 'constants/defaults'; import useIsL2 from 'hooks/useIsL2'; import useNetworkSwitcher from 'hooks/useNetworkSwitcher'; @@ -144,9 +144,7 @@ const OpenOrdersTable: React.FC = () => { columns={[ { Header: ( - - {t('futures.market.user.open-orders.table.market-type')} - + {t('futures.market.user.open-orders.table.market-type')} ), accessor: 'market', Cell: (cellProps: CellProps) => { @@ -171,11 +169,7 @@ const OpenOrdersTable: React.FC = () => { width: 60, }, { - Header: ( - - {t('futures.market.user.open-orders.table.side')} - - ), + Header: {t('futures.market.user.open-orders.table.side')}, accessor: 'side', Cell: (cellProps: CellProps) => { return ( @@ -188,11 +182,7 @@ const OpenOrdersTable: React.FC = () => { width: 40, }, { - Header: ( - - {t('futures.market.user.open-orders.table.size')} - - ), + Header: {t('futures.market.user.open-orders.table.size')}, accessor: 'size', Cell: (cellProps: CellProps) => { return ( @@ -206,9 +196,9 @@ const OpenOrdersTable: React.FC = () => { }, { Header: ( - + {t('futures.market.user.open-orders.table.commit-deposit')} - + ), accessor: 'marginDelta', Cell: (cellProps: CellProps) => { @@ -220,9 +210,7 @@ const OpenOrdersTable: React.FC = () => { }, { Header: ( - - {t('futures.market.user.open-orders.table.status')} - + {t('futures.market.user.open-orders.table.status')} ), accessor: 'actions', Cell: (cellProps: CellProps) => { @@ -266,9 +254,7 @@ const OpenOrdersTable: React.FC = () => { columns={[ { Header: ( - - {t('futures.market.user.open-orders.table.side-type')} - + {t('futures.market.user.open-orders.table.side-type')} ), accessor: 'side/type', Cell: (cellProps: CellProps) => ( @@ -282,11 +268,7 @@ const OpenOrdersTable: React.FC = () => { width: 100, }, { - Header: ( - - {t('futures.market.user.open-orders.table.size')} - - ), + Header: {t('futures.market.user.open-orders.table.size')}, accessor: 'size', Cell: (cellProps: CellProps) => { return ( @@ -313,11 +295,6 @@ const StyledTable = styled(Table)` margin-bottom: 20px; `; -const StyledTableHeader = styled.div` - font-family: ${(props) => props.theme.fonts.regular}; - text-transform: capitalize; -`; - const StyledCurrencyIcon = styled(Currency.Icon)` width: 30px; height: 30px; diff --git a/sections/futures/MobileTrade/common.ts b/sections/futures/mobile.ts similarity index 100% rename from sections/futures/MobileTrade/common.ts rename to sections/futures/mobile.ts diff --git a/sections/homepage/Assets/Assets.tsx b/sections/homepage/Assets.tsx similarity index 90% rename from sections/homepage/Assets/Assets.tsx rename to sections/homepage/Assets.tsx index 998acefc56..3fdf2933d5 100644 --- a/sections/homepage/Assets/Assets.tsx +++ b/sections/homepage/Assets.tsx @@ -1,6 +1,5 @@ import { wei } from '@synthetixio/wei'; import { ColorType, createChart, UTCTimestamp } from 'lightweight-charts'; -import isNil from 'lodash/isNil'; import values from 'lodash/values'; import router from 'next/router'; import React, { useEffect, useMemo, useRef, useState } from 'react'; @@ -14,10 +13,10 @@ import GridSvg from 'assets/svg/app/grid.svg'; import Button from 'components/Button'; import ChangePercent from 'components/ChangePercent'; import Currency from 'components/Currency'; +import { FlexDiv, FlexDivColCentered, FlexDivRow } from 'components/layout/flex'; import { TabPanel } from 'components/Tab'; import { CurrencyKey } from 'constants/currency'; import Connector from 'containers/Connector'; -import { Price } from 'queries/rates/types'; import { requestCandlesticks } from 'queries/rates/useCandlesticksQuery'; import useGetSynthsTradingVolumeForAllMarkets from 'queries/synths/useGetSynthsTradingVolumeForAllMarkets'; import { selectMarketVolumes } from 'state/futures/selectors'; @@ -26,13 +25,7 @@ import { selectOptimismMarkets } from 'state/home/selectors'; import { useAppSelector, usePollAction } from 'state/hooks'; import { selectPrices } from 'state/prices/selectors'; import { pastRatesState } from 'store/futures'; -import { - FlexDiv, - FlexDivColCentered, - FlexDivRow, - SmallGoldenHeader, - WhiteHeader, -} from 'styles/common'; +import { SmallGoldenHeader, WhiteHeader } from 'styles/common'; import media, { Media } from 'styles/media'; import { getSynthDescription } from 'utils/futures'; @@ -149,7 +142,7 @@ export const PriceChart = ({ asset }: PriceChartProps) => { const Assets = () => { const { t } = useTranslation(); const { l2SynthsMap, l2Provider } = Connector.useContainer(); - const [activeMarketsTab, setActiveMarketsTab] = useState(MarketsTab.FUTURES); + const [activeMarketsTab, setActiveMarketsTab] = useState(MarketsTab.FUTURES); const prices = useAppSelector(selectPrices); const futuresMarkets = useAppSelector(selectOptimismMarkets); @@ -188,7 +181,7 @@ const Assets = () => { const frozenSynthsQuery = queryCache.find(['synths', 'frozenSynths', 10]); const unfrozenSynths = - frozenSynthsQuery && frozenSynthsQuery.state.status === 'success' + frozenSynthsQuery?.state.status === 'success' ? synths.filter( (synth) => !(frozenSynthsQuery.state.data as Set).has(synth.name) ) @@ -198,30 +191,27 @@ const Assets = () => { const synthVolumesQuery = useGetSynthsTradingVolumeForAllMarkets(yesterday); const PERPS = useMemo(() => { - return ( - futuresMarkets?.map((market) => { - const marketPrice = - prices[market.asset]?.offChain ?? prices[market.asset]?.onChain ?? wei(0); - const description = getSynthDescription(market.asset, l2SynthsMap, t); - const volume = futuresVolumes[market.assetHex]?.volume?.toNumber() ?? 0; - const pastPrice = pastRates.find( - (price: Price) => price.synth === market.asset || price.synth === market.asset.slice(1) - ); - return { - key: market.asset, - name: market.asset[0] === 's' ? market.asset.slice(1) : market.asset, - description: description.split(' ')[0], - price: marketPrice.toNumber(), - volume, - priceChange: - (marketPrice.toNumber() - (pastPrice?.price ?? 0)) / marketPrice.toNumber() || 0, - image: , - icon: ( - - ), - }; - }) ?? [] - ); + return futuresMarkets.map((market) => { + const marketPrice = prices[market.asset]?.offChain ?? prices[market.asset]?.onChain ?? wei(0); + const description = getSynthDescription(market.asset, l2SynthsMap, t); + const volume = futuresVolumes[market.assetHex]?.volume?.toNumber() ?? 0; + const pastPrice = pastRates.find( + (price) => price.synth === market.asset || price.synth === market.asset.slice(1) + ); + return { + key: market.asset, + name: market.asset[0] === 's' ? market.asset.slice(1) : market.asset, + description: description.split(' ')[0], + price: marketPrice.toNumber(), + volume, + priceChange: + (marketPrice.toNumber() - (pastPrice?.price ?? 0)) / marketPrice.toNumber() || 0, + image: , + icon: ( + + ), + }; + }); // eslint-disable-next-line }, [futuresMarkets, l2SynthsMap, pastRates, futuresVolumes, t]); @@ -234,10 +224,10 @@ const Assets = () => { currencyName: synth.description, }) : ''; - const rate = prices && (prices[synth.name]?.onChain || prices[synth.name]?.offChain); - const price = isNil(rate) ? 0 : rate.toNumber(); + const rate = prices?.[synth.name]?.onChain || prices?.[synth.name]?.offChain; + const price = rate?.toNumber() ?? 0; - const pastPrice = pastRates.find((price: Price) => { + const pastPrice = pastRates.find((price) => { return price.synth === synth.asset || price.synth === synth.name; }); @@ -247,7 +237,7 @@ const Assets = () => { description: description.slice(10), price, change: price !== 0 ? (price - (pastPrice?.price ?? 0)) / price || 0 : 0, - volume: !isNil(synthVolumes[synth.name]) ? Number(synthVolumes[synth.name]) ?? 0 : 0, + volume: synthVolumes[synth.name]?.toNumber() ?? 0, image: , icon: ( @@ -310,9 +300,9 @@ const Assets = () => { {image} @@ -331,9 +321,9 @@ const Assets = () => { <>- ) : ( @@ -370,9 +360,9 @@ const Assets = () => { {image} @@ -391,9 +381,9 @@ const Assets = () => { <>- ) : ( @@ -440,9 +430,9 @@ const Assets = () => { {image} @@ -461,9 +451,9 @@ const Assets = () => { <>- ) : ( @@ -499,9 +489,9 @@ const Assets = () => { {image} @@ -520,9 +510,9 @@ const Assets = () => { <>- ) : ( diff --git a/sections/homepage/Assets/index.ts b/sections/homepage/Assets/index.ts deleted file mode 100644 index f7e0f87fd6..0000000000 --- a/sections/homepage/Assets/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './Assets'; diff --git a/sections/homepage/Earning/Earning.tsx b/sections/homepage/Earning.tsx similarity index 93% rename from sections/homepage/Earning/Earning.tsx rename to sections/homepage/Earning.tsx index d037816a15..4714ac3030 100644 --- a/sections/homepage/Earning/Earning.tsx +++ b/sections/homepage/Earning.tsx @@ -5,19 +5,18 @@ import styled from 'styled-components'; import StakeNEarnIcon from 'assets/svg/earn/stake-n-earn.svg'; import TradeNEarnIcon from 'assets/svg/earn/trade-n-earn.svg'; import VoteNGovernIcon from 'assets/svg/earn/vote-n-govern.svg'; +import { StackSection } from 'sections/homepage/section'; +import { Copy, Title } from 'sections/homepage/text'; import { FlexDivCentered, FlexDivCol, FlexDivColCentered, FlexDivRow, - GridDiv, - SmallGoldenHeader, - WhiteHeader, -} from 'styles/common'; +} from 'components/layout/flex'; +import { GridDiv } from 'components/layout/grid'; +import { SmallGoldenHeader, WhiteHeader } from 'styles/common'; import media, { Media } from 'styles/media'; -import { Copy, StackSection, Title } from '../common'; - const EARNINGS = [ { id: 'vote-and-govern', diff --git a/sections/homepage/Earning/index.ts b/sections/homepage/Earning/index.ts deleted file mode 100644 index 2706892636..0000000000 --- a/sections/homepage/Earning/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './Earning'; diff --git a/sections/homepage/Features/Features.tsx b/sections/homepage/Features.tsx similarity index 97% rename from sections/homepage/Features/Features.tsx rename to sections/homepage/Features.tsx index 440283ad43..dee4d54546 100644 --- a/sections/homepage/Features/Features.tsx +++ b/sections/homepage/Features.tsx @@ -23,14 +23,12 @@ import { FlexDivCol, FlexDivColCentered, FlexDivRow, - GridDivCentered, - SmallGoldenHeader, - WhiteHeader, -} from 'styles/common'; +} from 'components/layout/flex'; +import { GridDivCentered } from 'components/layout/grid'; +import { Copy, Title } from 'sections/homepage/text'; +import { SmallGoldenHeader, WhiteHeader } from 'styles/common'; import media from 'styles/media'; -import { Copy, Title } from '../common'; - const FEATURES = [ { key: 'blazing-fast', diff --git a/sections/homepage/Features/index.ts b/sections/homepage/Features/index.ts deleted file mode 100644 index b5fde73644..0000000000 --- a/sections/homepage/Features/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './Features'; diff --git a/sections/homepage/Hero/Hero.tsx b/sections/homepage/Hero.tsx similarity index 88% rename from sections/homepage/Hero/Hero.tsx rename to sections/homepage/Hero.tsx index 02d93c2532..ce6769759e 100644 --- a/sections/homepage/Hero/Hero.tsx +++ b/sections/homepage/Hero.tsx @@ -5,15 +5,16 @@ import styled from 'styled-components'; import MarketOrderPreview from 'assets/png/marketing/market-order-preview.png'; import Button from 'components/Button'; +import { StackSection } from 'sections/homepage/section'; +import { FlexDivColCentered } from 'components/layout/flex'; +import { GridDiv } from 'components/layout/grid'; import PoweredBySynthetix from 'components/PoweredBySynthetix'; +import * as Text from 'components/Text'; import Webp from 'components/Webp'; import { DEFAULT_FUTURES_MARGIN_TYPE } from 'constants/defaults'; import ROUTES from 'constants/routes'; -import { FlexDivColCentered, GridDiv, Paragraph } from 'styles/common'; import media from 'styles/media'; -import { StackSection } from '../common'; - const Hero = () => { const { t } = useTranslation(); @@ -53,8 +54,7 @@ const Emphasis = styled.b` color: ${(props) => props.theme.colors.common.primaryWhite}; `; -const Header = styled(Paragraph)` - font-family: ${(props) => props.theme.fonts.monoBold}; +const Header = styled(Text.Body).attrs({ variant: 'bold', mono: true })` max-width: 636px; font-size: 80px; line-height: 85%; @@ -68,8 +68,7 @@ const Header = styled(Paragraph)` `} `; -const ProductDescription = styled(Paragraph)` - font-family: ${(props) => props.theme.fonts.regular}; +const ProductDescription = styled(Text.Body)` max-width: 530px; font-size: 24px; line-height: 120%; diff --git a/sections/homepage/Hero/index.ts b/sections/homepage/Hero/index.ts deleted file mode 100644 index 9c292bc06d..0000000000 --- a/sections/homepage/Hero/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './Hero'; diff --git a/sections/homepage/ShortList/ShortList.tsx b/sections/homepage/ShortList.tsx similarity index 95% rename from sections/homepage/ShortList/ShortList.tsx rename to sections/homepage/ShortList.tsx index 3c1f37ebdc..bdf2dd7254 100644 --- a/sections/homepage/ShortList/ShortList.tsx +++ b/sections/homepage/ShortList.tsx @@ -7,18 +7,19 @@ import styled from 'styled-components'; import GridSvg from 'assets/svg/app/grid.svg'; import Button from 'components/Button'; import Currency from 'components/Currency'; +import { FlexDivColCentered, FlexDivRow } from 'components/layout/flex'; import Loader from 'components/Loader'; -import Table from 'components/Table'; +import Table, { TableHeader } from 'components/Table'; import ROUTES from 'constants/routes'; import useENS from 'hooks/useENS'; import useGetFuturesCumulativeStats from 'queries/futures/useGetFuturesCumulativeStats'; import useGetStats from 'queries/futures/useGetStats'; -import { FlexDivColCentered, FlexDivRow, SmallGoldenHeader, WhiteHeader } from 'styles/common'; +import { StackSection } from 'sections/homepage/section'; +import { Title } from 'sections/homepage/text'; +import { SmallGoldenHeader, WhiteHeader } from 'styles/common'; import media, { Media } from 'styles/media'; import { formatDollars, formatNumber, zeroBN } from 'utils/formatters/number'; -import { StackSection, Title } from '../common'; - const ShortList = () => { const { t } = useTranslation(); @@ -134,9 +135,9 @@ const ShortList = () => { accessor: 'pnl', Cell: (cellProps: CellProps) => ( ), @@ -197,9 +198,9 @@ const ShortList = () => { accessor: 'pnl', Cell: (cellProps: CellProps) => ( ), @@ -343,12 +344,6 @@ const Container = styled(FlexDivColCentered)` justify-content: center; `; -const TableHeader = styled.div` - font-family: ${(props) => props.theme.fonts.regular}; - color: ${(props) => props.theme.colors.common.secondaryGray}; - font-size: 13px; -`; - const StyledOrderType = styled.div` color: ${(props) => props.theme.colors.white}; text-align: center; diff --git a/sections/homepage/ShortList/index.ts b/sections/homepage/ShortList/index.ts deleted file mode 100644 index 1bd07f9f9f..0000000000 --- a/sections/homepage/ShortList/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './ShortList'; diff --git a/sections/homepage/TradeNow/TradeNow.tsx b/sections/homepage/TradeNow.tsx similarity index 92% rename from sections/homepage/TradeNow/TradeNow.tsx rename to sections/homepage/TradeNow.tsx index a557623e3c..33dd8e1d15 100644 --- a/sections/homepage/TradeNow/TradeNow.tsx +++ b/sections/homepage/TradeNow.tsx @@ -4,9 +4,11 @@ import { useTranslation } from 'react-i18next'; import styled from 'styled-components'; import Button from 'components/Button'; +import { FlexDivColCentered } from 'components/layout/flex'; +import * as Text from 'components/Text'; import { DEFAULT_FUTURES_MARGIN_TYPE } from 'constants/defaults'; import ROUTES from 'constants/routes'; -import { FlexDivColCentered, Paragraph, SmallGoldenHeader, WhiteHeader } from 'styles/common'; +import { SmallGoldenHeader, WhiteHeader } from 'styles/common'; import media from 'styles/media'; const TradeNow = () => { @@ -68,7 +70,7 @@ const Container = styled.div` `}; `; -const GrayDescription = styled(Paragraph)` +const GrayDescription = styled(Text.Body)` color: ${(props) => props.theme.colors.common.secondaryGray}; font-size: 24px; line-height: 120%; diff --git a/sections/homepage/TradeNow/index.ts b/sections/homepage/TradeNow/index.ts deleted file mode 100644 index 47d8ab1321..0000000000 --- a/sections/homepage/TradeNow/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './TradeNow'; diff --git a/sections/homepage/containers/SmoothScroll/SmoothScroll.tsx b/sections/homepage/containers/SmoothScroll/SmoothScroll.tsx deleted file mode 100644 index 72db4ca4b4..0000000000 --- a/sections/homepage/containers/SmoothScroll/SmoothScroll.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import { MutableRefObject, useRef } from 'react'; -import { createContainer } from 'unstated-next'; - -const useSmoothScroll = () => { - const whyKwentaRef = useRef(null); - const howItWorksRef = useRef(null); - const faqRef = useRef(null); - - const scrollToRef = (ref: MutableRefObject) => { - if (ref && ref.current) { - ref.current.scrollIntoView({ - behavior: 'smooth', - }); - } - }; - - return { - whyKwentaRef, - howItWorksRef, - faqRef, - scrollToRef, - }; -}; - -const SmoothScroll = createContainer(useSmoothScroll); - -export default SmoothScroll; diff --git a/sections/homepage/containers/SmoothScroll/index.tsx b/sections/homepage/containers/SmoothScroll/index.tsx deleted file mode 100644 index 29d4e373ae..0000000000 --- a/sections/homepage/containers/SmoothScroll/index.tsx +++ /dev/null @@ -1 +0,0 @@ -export { default } from './SmoothScroll'; diff --git a/sections/homepage/containers/index.tsx b/sections/homepage/containers/index.tsx deleted file mode 100644 index 4029c1c5e5..0000000000 --- a/sections/homepage/containers/index.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import React, { FC } from 'react'; - -import SmoothScroll from './SmoothScroll'; - -type WithHomepageContainersProps = { - children: React.ReactNode; -}; - -export const WithHomepageContainers: FC = ({ children }) => ( - {children} -); - -export default WithHomepageContainers; diff --git a/sections/homepage/common.tsx b/sections/homepage/section.ts similarity index 50% rename from sections/homepage/common.tsx rename to sections/homepage/section.ts index d50ddba040..17e6b091b3 100644 --- a/sections/homepage/common.tsx +++ b/sections/homepage/section.ts @@ -1,6 +1,7 @@ import styled from 'styled-components'; -import { FlexDivColCentered, GridDiv, Paragraph } from 'styles/common'; +import { FlexDivColCentered } from 'components/layout/flex'; +import { GridDiv } from 'components/layout/grid'; import media from 'styles/media'; export const StackSection = styled(FlexDivColCentered)` @@ -19,18 +20,3 @@ export const GridContainer = styled(GridDiv)` grid-template-columns: 1fr; `} `; - -export const Title = styled(Paragraph)` - font-size: 16px; - font-family: ${(props) => props.theme.fonts.bold}; - text-align: left; - color: ${(props) => props.theme.colors.selectedTheme.button.text.primary}; -`; - -export const Copy = styled(Paragraph)` - font-size: 16px; - font-style: normal; - line-height: 24px; - text-align: left; - color: ${(props) => props.theme.colors.silver}; -`; diff --git a/sections/homepage/text.ts b/sections/homepage/text.ts new file mode 100644 index 0000000000..7aef0b1b1a --- /dev/null +++ b/sections/homepage/text.ts @@ -0,0 +1,17 @@ +import styled from 'styled-components'; + +import { Body } from 'components/Text'; + +export const Title = styled(Body).attrs({ variant: 'bold' })` + font-size: 16px; + text-align: left; + color: ${(props) => props.theme.colors.selectedTheme.button.text.primary}; +`; + +export const Copy = styled(Body)` + font-size: 16px; + font-style: normal; + line-height: 24px; + text-align: left; + color: ${(props) => props.theme.colors.silver}; +`; diff --git a/sections/leaderboard/AllTime/AllTime.tsx b/sections/leaderboard/AllTime.tsx similarity index 93% rename from sections/leaderboard/AllTime/AllTime.tsx rename to sections/leaderboard/AllTime.tsx index c213395e06..e5bebb2804 100644 --- a/sections/leaderboard/AllTime/AllTime.tsx +++ b/sections/leaderboard/AllTime.tsx @@ -5,13 +5,13 @@ import styled from 'styled-components'; import Currency from 'components/Currency'; import { MobileHiddenView, MobileOnlyView } from 'components/Media'; -import Table from 'components/Table'; +import Table, { TableHeader } from 'components/Table'; import { DEFAULT_LEADERBOARD_ROWS } from 'constants/defaults'; import Connector from 'containers/Connector'; import useENSAvatar from 'hooks/useENSAvatar'; import { AccountStat } from 'queries/futures/types'; - -import { getMedal, StyledTrader } from '../common'; +import { StyledTrader } from 'sections/leaderboard/trader'; +import { getMedal } from 'utils/competition'; type AllTimeProps = { stats: AccountStat[]; @@ -34,7 +34,7 @@ const AllTime: FC = ({ const { staticMainnetProvider, walletAddress } = Connector.useContainer(); if (compact) { - const ownPosition = stats.findIndex((i: { account: string }) => { + const ownPosition = stats.findIndex((i) => { return i.account.toLowerCase() === walletAddress?.toLowerCase(); }); @@ -146,9 +146,9 @@ const AllTime: FC = ({ accessor: 'totalVolume', Cell: (cellProps: CellProps) => ( ), @@ -159,9 +159,9 @@ const AllTime: FC = ({ accessor: 'pnl', Cell: (cellProps: CellProps) => ( ), @@ -230,7 +230,7 @@ const AllTime: FC = ({ Header: () => {t('leaderboard.leaderboard.table.pnl')}, accessor: 'pnl', Cell: (cellProps: CellProps) => ( - + ), width: 125, }, @@ -267,11 +267,6 @@ const TitleText = styled.div` text-transform: capitalize; `; -const TableHeader = styled.div` - font-family: ${(props) => props.theme.fonts.regular}; - color: ${(props) => props.theme.colors.selectedTheme.gray}; -`; - const StyledOrderType = styled.div` color: ${(props) => props.theme.colors.selectedTheme.button.text.primary}; display: flex; diff --git a/sections/leaderboard/AllTime/index.tsx b/sections/leaderboard/AllTime/index.tsx deleted file mode 100644 index 021d28694d..0000000000 --- a/sections/leaderboard/AllTime/index.tsx +++ /dev/null @@ -1 +0,0 @@ -export { default } from './AllTime'; diff --git a/sections/leaderboard/Competition/Competition.tsx b/sections/leaderboard/Competition.tsx similarity index 92% rename from sections/leaderboard/Competition/Competition.tsx rename to sections/leaderboard/Competition.tsx index 553a17c7f4..61f9d864a7 100644 --- a/sections/leaderboard/Competition/Competition.tsx +++ b/sections/leaderboard/Competition.tsx @@ -6,17 +6,17 @@ import styled from 'styled-components'; import Currency from 'components/Currency'; import { DesktopOnlyView, MobileOrTabletView } from 'components/Media'; -import Table, { TableNoResults } from 'components/Table'; +import Table, { TableHeader, TableNoResults } from 'components/Table'; +import { CompetitionRound, PIN, Tier } from 'constants/competition'; import Connector from 'containers/Connector'; import useENSs from 'hooks/useENSs'; import useGetFile from 'queries/files/useGetFile'; import { AccountStat } from 'queries/futures/types'; +import { StyledTrader } from 'sections/leaderboard/trader'; +import { getMedal, getCompetitionDataLocation } from 'utils/competition'; import { formatPercent } from 'utils/formatters/number'; import { truncateAddress } from 'utils/formatters/string'; -import { CompetitionRound, getMedal, PIN, StyledTrader, Tier } from '../common'; -import { getCompetitionDataLocation } from './constants'; - type CompetitionProps = { round: CompetitionRound; activeTier: Tier; @@ -45,10 +45,7 @@ const Competition: FC = ({ }, [walletAddress, competitionQuery]); const traders = useMemo( - () => - competitionQuery?.data?.map((stat: AccountStat) => { - return stat.account; - }) ?? [], + () => competitionQuery?.data?.map((stat: AccountStat) => stat.account) ?? [], [competitionQuery?.data] ); @@ -86,10 +83,7 @@ const Competition: FC = ({ const pinRow = cleanCompetitionData .filter((trader) => trader.account.toLowerCase() === walletAddress?.toLowerCase()) - .map((trader) => ({ - ...trader, - rankText: `${trader.rank}${PIN}`, - })); + .map((trader) => ({ ...trader, rankText: `${trader.rank}${PIN}` })); return [...pinRow, ...cleanCompetitionData]; }, [competitionQuery, ensInfo, searchTerm, activeTier, walletAddress, walletTier, compact]); @@ -169,9 +163,9 @@ const Competition: FC = ({ sortType: 'basic', Cell: (cellProps: CellProps) => ( ), @@ -183,11 +177,11 @@ const Competition: FC = ({ accessor: 'pnlNumber', sortType: 'basic', Cell: (cellProps: CellProps) => ( - + {cellProps.row.original.pnlPct} @@ -237,9 +231,9 @@ const Competition: FC = ({ Cell: (cellProps: CellProps) => ( {cellProps.row.original.pnlPct} @@ -269,11 +263,6 @@ const TitleText = styled.a` color: ${(props) => props.theme.colors.selectedTheme.gray}; `; -const TableHeader = styled.div` - font-family: ${(props) => props.theme.fonts.regular}; - color: ${(props) => props.theme.colors.selectedTheme.gray}; -`; - const PnlContainer = styled.div<{ direction: 'row' | 'column' }>` display: flex; flex-direction: ${(props) => props.direction}; diff --git a/sections/leaderboard/Competition/constants.tsx b/sections/leaderboard/Competition/constants.tsx deleted file mode 100644 index 68d26b4df6..0000000000 --- a/sections/leaderboard/Competition/constants.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import { CompetitionRound } from '../common'; - -export const getCompetitionDataLocation = (round: CompetitionRound) => { - return `crossmargin_competition_${round}/leaderboard_latest.json`; -}; diff --git a/sections/leaderboard/Competition/index.tsx b/sections/leaderboard/Competition/index.tsx deleted file mode 100644 index b2263d9773..0000000000 --- a/sections/leaderboard/Competition/index.tsx +++ /dev/null @@ -1 +0,0 @@ -export { default } from './Competition'; diff --git a/sections/leaderboard/Leaderboard/Leaderboard.tsx b/sections/leaderboard/Leaderboard.tsx similarity index 87% rename from sections/leaderboard/Leaderboard/Leaderboard.tsx rename to sections/leaderboard/Leaderboard.tsx index 435bc9fdb0..0a038e8786 100644 --- a/sections/leaderboard/Leaderboard/Leaderboard.tsx +++ b/sections/leaderboard/Leaderboard.tsx @@ -4,20 +4,20 @@ import { FC, useCallback, useEffect, useMemo, useState } from 'react'; import styled from 'styled-components'; import TabButton from 'components/Button/TabButton'; +import { FlexDivCol } from 'components/layout/flex'; import Search from 'components/Table/Search'; +import { CompetitionRound, COMPETITION_TIERS, PIN, Tier } from 'constants/competition'; import ROUTES from 'constants/routes'; import useENS from 'hooks/useENS'; import useENSs from 'hooks/useENSs'; import { AccountStat } from 'queries/futures/types'; import useLeaderboard, { DEFAULT_LEADERBOARD_DATA } from 'queries/futures/useLeaderboard'; import { CompetitionBanner } from 'sections/shared/components/CompetitionBanner'; -import { FlexDivCol } from 'styles/common'; import media from 'styles/media'; -import AllTime from '../AllTime'; -import { CompetitionRound, COMPETITION_TIERS, PIN, Tier } from '../common'; -import Competition from '../Competition'; -import TraderHistory from '../TraderHistory'; +import AllTime from './AllTime'; +import Competition from './Competition'; +import TraderHistory from './TraderHistory'; type LeaderboardProps = { compact?: boolean; @@ -31,8 +31,8 @@ enum LeaderboardTab { const LEADERBOARD_TABS = [LeaderboardTab.Top, LeaderboardTab.Bottom]; -const Leaderboard: FC = ({ compact, mobile }: LeaderboardProps) => { - const [activeTab, setActiveTab] = useState(LeaderboardTab.Top); +const Leaderboard: FC = ({ compact, mobile }) => { + const [activeTab, setActiveTab] = useState(LeaderboardTab.Top); const [activeTier, setActiveTier] = useState('bronze'); const [competitionRound, setCompetitionRound] = useState(); const [searchInput, setSearchInput] = useState(''); @@ -47,24 +47,16 @@ const Leaderboard: FC = ({ compact, mobile }: LeaderboardProps leaderboardQuery, ]); - const traders = useMemo( - () => - leaderboardData.all?.map((stat: AccountStat) => { - return stat.account; - }) ?? [], - [leaderboardData] - ); + const traders = useMemo(() => leaderboardData.all?.map((stat) => stat.account) ?? [], [ + leaderboardData, + ]); const ensInfoQuery = useENSs(traders); const ensInfo = useMemo(() => ensInfoQuery.data ?? {}, [ensInfoQuery]); - const pinRow: AccountStat[] = useMemo(() => { + const pinRow = useMemo(() => { return leaderboardData.wallet - ? leaderboardData.wallet.map((trader) => ({ - ...trader, - rank: 0, - rankText: PIN, - })) + ? leaderboardData.wallet.map((trader) => ({ ...trader, rank: 0, rankText: PIN })) : []; }, [leaderboardData.wallet]); @@ -85,7 +77,7 @@ const Leaderboard: FC = ({ compact, mobile }: LeaderboardProps return null; }, [router.query, router.asPath]); - const onChangeSearch = async (text: string) => { + const onChangeSearch = (text: string) => { setSearchInput(text?.toLowerCase()); if (isAddress(text)) { @@ -119,16 +111,11 @@ const Leaderboard: FC = ({ compact, mobile }: LeaderboardProps }; useEffect(() => { - setSearchAddress( - searchEns.ensAddress ? searchEns.ensAddress : isAddress(searchTerm) ? searchTerm : '' - ); + setSearchAddress(searchEns.ensAddress ?? (isAddress(searchTerm) ? searchTerm : '')); }, [searchTerm, searchEns]); const mapEnsName = useCallback( - (stat: AccountStat) => ({ - ...stat, - traderEns: ensInfo[stat.account] ?? null, - }), + (stat: AccountStat) => ({ ...stat, traderEns: ensInfo[stat.account] ?? null }), [ensInfo] ); diff --git a/sections/leaderboard/Leaderboard/index.tsx b/sections/leaderboard/Leaderboard/index.tsx deleted file mode 100644 index 7e4f019461..0000000000 --- a/sections/leaderboard/Leaderboard/index.tsx +++ /dev/null @@ -1 +0,0 @@ -export { default } from './Leaderboard'; diff --git a/sections/leaderboard/TraderHistory.tsx b/sections/leaderboard/TraderHistory.tsx new file mode 100644 index 0000000000..5528b897e6 --- /dev/null +++ b/sections/leaderboard/TraderHistory.tsx @@ -0,0 +1,368 @@ +import { wei, WeiSource } from '@synthetixio/wei'; +import router from 'next/router'; +import { FC, memo, useMemo } from 'react'; +import { useTranslation } from 'react-i18next'; +import { CellProps } from 'react-table'; +import styled, { css } from 'styled-components'; + +import Currency from 'components/Currency'; +import CurrencyIcon from 'components/Currency/CurrencyIcon'; +import { FlexDiv } from 'components/layout/flex'; +import { DesktopOnlyView, MobileOrTabletView } from 'components/Media'; +import FuturesIcon from 'components/Nav/FuturesIcon'; +import Table, { TableHeader } from 'components/Table'; +import ROUTES from 'constants/routes'; +import { FuturesAccountTypes } from 'queries/futures/types'; +import useGetFuturesPositionHistoryForAccount from 'queries/futures/useGetFuturesPositionHistoryForAccount'; +import TimeDisplay from 'sections/futures/Trades/TimeDisplay'; +import { ExternalLink } from 'styles/common'; +import { getMarketName } from 'utils/futures'; + +type TraderHistoryProps = { + trader: string; + ensInfo: Record; + resetSelection: Function; + compact?: boolean; + searchTerm?: string | undefined; +}; + +const TraderHistory: FC = memo( + ({ trader, ensInfo, resetSelection, compact, searchTerm }) => { + const { t } = useTranslation(); + const positionsQuery = useGetFuturesPositionHistoryForAccount(trader); + const positions = useMemo(() => { + const positionData = positionsQuery.data; + return positionData + ? [ + ...positionData[FuturesAccountTypes.ISOLATED_MARGIN], + ...positionData[FuturesAccountTypes.CROSS_MARGIN], + ] + : []; + }, [positionsQuery]); + const traderENSName = useMemo(() => ensInfo[trader] ?? null, [trader, ensInfo]); + + let data = useMemo(() => { + return positions + .sort((a, b) => b.timestamp - a.timestamp) + .map((stat, i) => { + return { + ...stat, + rank: i + 1, + currencyIconKey: stat.asset ? (stat.asset[0] !== 's' ? 's' : '') + stat.asset : '', + marketShortName: getMarketName(stat.asset), + status: stat.isOpen ? 'Open' : stat.isLiquidated ? 'Liquidated' : 'Closed', + pnl: stat.pnlWithFeesPaid, + pnlPct: `(${stat.pnlWithFeesPaid + .div(stat.initialMargin.add(stat.totalDeposits)) + .mul(100) + .toNumber() + .toFixed(2)}%)`, + }; + }) + .filter((i) => + searchTerm?.length + ? i.marketShortName.toLowerCase().includes(searchTerm) || + i.status.toLowerCase().includes(searchTerm) + : true + ); + }, [positions, searchTerm]); + + return ( + <> + + + { + resetSelection(); + }} + > + {t('leaderboard.trader-history.table.back')} + + > + + {traderENSName ?? trader} + + + ), + accessor: 'title', + columns: [ + { + Header: ( + {t('leaderboard.trader-history.table.timestamp')} + ), + accessor: 'openTimestamp', + Cell: (cellProps: CellProps) => { + return ( + + + + ); + }, + sortType: 'basic', + sortable: true, + width: compact ? 40 : 100, + }, + { + Header: ( + {t('leaderboard.trader-history.table.market')} + ), + accessor: 'asset', + Cell: (cellProps: CellProps) => ( + + + {cellProps.row.original.marketShortName} + + + ), + width: compact ? 40 : 100, + }, + { + Header: ( + {t('leaderboard.trader-history.table.status')} + ), + accessor: 'status', + Cell: (cellProps: CellProps) => { + return {cellProps.row.original.status}; + }, + width: compact ? 40 : 100, + }, + { + Header: ( + + {t('leaderboard.trader-history.table.total-trades')} + + ), + accessor: 'trades', + width: compact ? 40 : 100, + sortType: 'basic', + sortable: true, + }, + { + Header: ( + + {t('leaderboard.trader-history.table.total-volume')} + + ), + accessor: 'totalVolume', + Cell: (cellProps: CellProps) => ( + + ), + width: compact ? 40 : 100, + sortType: 'basic', + sortable: true, + }, + { + Header: ( + {t('leaderboard.trader-history.table.total-pnl')} + ), + accessor: 'pnl', + Cell: (cellProps: CellProps) => ( + + + + {cellProps.row.original.pnlPct} + + + ), + width: compact ? 40 : 100, + sortType: 'basic', + sortable: true, + }, + ], + }, + ]} + /> + + + + { + resetSelection(); + router.push(ROUTES.Leaderboard.Home); + }} + > + {t('leaderboard.leaderboard.table.title')} + + > + + {traderENSName ?? trader} + + + ), + accessor: 'title', + columns: [ + { + Header: ( + {t('leaderboard.trader-history.table.market')} + ), + accessor: 'asset', + Cell: (cellProps: CellProps) => ( + + + {cellProps.row.original.marketShortName} + + + ), + width: 50, + }, + { + Header: ( + {t('leaderboard.trader-history.table.status')} + ), + accessor: 'status', + Cell: (cellProps: CellProps) => { + return {cellProps.row.original.status}; + }, + width: 30, + }, + { + Header: ( + {t('leaderboard.trader-history.table.total-pnl')} + ), + accessor: 'pnl', + Cell: (cellProps: CellProps) => ( + + + + {cellProps.row.original.pnlPct} + + + ), + width: 40, + sortType: 'basic', + sortable: true, + }, + ], + }, + ]} + /> + + + ); + } +); + +const StyledTable = styled(Table)<{ compact?: boolean }>` + margin-top: ${({ compact }) => (compact ? '0' : '15px')}; +`; + +const TableTitle = styled.div` + width: 100%; + display: flex; + justify-content: flex-start; +`; + +const TitleText = styled.a` + font-family: ${(props) => props.theme.fonts.regular}; + color: ${(props) => props.theme.colors.selectedTheme.gray}; + + &:hover { + text-decoration: underline; + } +`; + +const StyledCell = styled.div` + color: ${(props) => props.theme.colors.selectedTheme.button.text.primary}; + display: flex; +`; + +const TitleSeparator = styled.div` + margin-left: 10px; + margin-right: 10px; + font-family: ${(props) => props.theme.fonts.regular}; + color: ${(props) => props.theme.colors.selectedTheme.gray}; +`; + +const StyledCurrencyIcon = styled(CurrencyIcon)` + width: 30px; + height: 30px; + margin-right: 5px; +`; + +const CurrencyInfo = styled(FlexDiv)` + align-items: center; +`; + +const StyledSubtitle = styled.div` + font-family: ${(props) => props.theme.fonts.regular}; + font-size: 13px; + color: ${(props) => props.theme.colors.selectedTheme.button.text.primary}; + text-transform: capitalize; +`; + +const PnlContainer = styled.div` + display: flex; + flex-direction: column; + align-items: center; +`; + +const valueColor = css<{ $value: WeiSource }>` + color: ${(props) => + wei(props.$value).gt(0) + ? props.theme.colors.selectedTheme.green + : wei(props.$value).lt(0) + ? props.theme.colors.selectedTheme.red + : props.theme.colors.selectedTheme.button.text.primary}; +`; + +const ColorCodedPrice = styled(Currency.Price)<{ $value: WeiSource }>` + align-items: right; + ${valueColor} +`; + +const StyledValue = styled.div<{ $value: WeiSource }>` + font-family: ${(props) => props.theme.fonts.mono}; + font-size: 13px; + margin: 0; + text-align: end; + ${valueColor} +`; + +const StyledFuturesIcon = styled(FuturesIcon)` + margin-left: 5px; +`; + +export default TraderHistory; diff --git a/sections/leaderboard/TraderHistory/TraderHistory.tsx b/sections/leaderboard/TraderHistory/TraderHistory.tsx deleted file mode 100644 index 61c3ad37ef..0000000000 --- a/sections/leaderboard/TraderHistory/TraderHistory.tsx +++ /dev/null @@ -1,390 +0,0 @@ -import router from 'next/router'; -import { FC, useMemo } from 'react'; -import { useTranslation } from 'react-i18next'; -import { CellProps } from 'react-table'; -import styled from 'styled-components'; - -import Currency from 'components/Currency'; -import CurrencyIcon from 'components/Currency/CurrencyIcon'; -import { DesktopOnlyView, MobileOrTabletView } from 'components/Media'; -import FuturesIcon from 'components/Nav/FuturesIcon'; -import Table from 'components/Table'; -import ROUTES from 'constants/routes'; -import { FuturesAccountTypes, PositionHistory } from 'queries/futures/types'; -import useGetFuturesPositionHistoryForAccount from 'queries/futures/useGetFuturesPositionHistoryForAccount'; -import TimeDisplay from 'sections/futures/Trades/TimeDisplay'; -import { FlexDiv } from 'styles/common'; -import { getMarketName } from 'utils/futures'; - -type TraderHistoryProps = { - trader: string; - ensInfo: Record; - resetSelection: Function; - compact?: boolean; - searchTerm?: string | undefined; -}; - -const TraderHistory: FC = ({ - trader, - ensInfo, - resetSelection, - compact, - searchTerm, -}: TraderHistoryProps) => { - const { t } = useTranslation(); - const positionsQuery = useGetFuturesPositionHistoryForAccount(trader); - const positions = useMemo(() => { - const positionData = positionsQuery.data; - return positionData - ? [ - ...positionData[FuturesAccountTypes.ISOLATED_MARGIN], - ...positionData[FuturesAccountTypes.CROSS_MARGIN], - ] - : []; - }, [positionsQuery]); - const traderENSName = useMemo(() => ensInfo[trader] ?? null, [trader, ensInfo]); - - let data = useMemo(() => { - return positions - .sort((a: PositionHistory, b: PositionHistory) => b.timestamp - a.timestamp) - .map((stat: PositionHistory, i: number) => { - return { - ...stat, - rank: i + 1, - currencyIconKey: stat.asset ? (stat.asset[0] !== 's' ? 's' : '') + stat.asset : '', - marketShortName: getMarketName(stat.asset), - status: stat.isOpen ? 'Open' : stat.isLiquidated ? 'Liquidated' : 'Closed', - pnl: stat.pnlWithFeesPaid, - pnlPct: `(${stat.pnlWithFeesPaid - .div(stat.initialMargin.add(stat.totalDeposits)) - .mul(100) - .toNumber() - .toFixed(2)}%)`, - }; - }) - .filter((i: { marketShortName: string; status: string }) => - searchTerm?.length - ? i.marketShortName.toLowerCase().includes(searchTerm) || - i.status.toLowerCase().includes(searchTerm) - : true - ); - }, [positions, searchTerm]); - - return ( - <> - - - { - resetSelection(); - }} - > - {t('leaderboard.trader-history.table.back')} - - > - - {traderENSName ?? trader} - - - ), - accessor: 'title', - columns: [ - { - Header: ( - {t('leaderboard.trader-history.table.timestamp')} - ), - accessor: 'openTimestamp', - Cell: (cellProps: CellProps) => { - return ( - - - - ); - }, - sortType: 'basic', - sortable: true, - width: compact ? 40 : 100, - }, - { - Header: {t('leaderboard.trader-history.table.market')}, - accessor: 'asset', - Cell: (cellProps: CellProps) => ( - - - {cellProps.row.original.marketShortName} - - - ), - width: compact ? 40 : 100, - }, - { - Header: {t('leaderboard.trader-history.table.status')}, - accessor: 'status', - Cell: (cellProps: CellProps) => { - return {cellProps.row.original.status}; - }, - width: compact ? 40 : 100, - }, - { - Header: ( - {t('leaderboard.trader-history.table.total-trades')} - ), - accessor: 'trades', - width: compact ? 40 : 100, - sortType: 'basic', - sortable: true, - }, - { - Header: ( - {t('leaderboard.trader-history.table.total-volume')} - ), - accessor: 'totalVolume', - Cell: (cellProps: CellProps) => ( - - ), - width: compact ? 40 : 100, - sortType: 'basic', - sortable: true, - }, - { - Header: ( - {t('leaderboard.trader-history.table.total-pnl')} - ), - accessor: 'pnl', - Cell: (cellProps: CellProps) => ( - - - - {cellProps.row.original.pnlPct} - - - ), - width: compact ? 40 : 100, - sortType: 'basic', - sortable: true, - }, - ], - }, - ]} - /> - - - - { - resetSelection(); - router.push(ROUTES.Leaderboard.Home); - }} - > - {t('leaderboard.leaderboard.table.title')} - - > - - {traderENSName ?? trader} - - - ), - accessor: 'title', - columns: [ - { - Header: {t('leaderboard.trader-history.table.market')}, - accessor: 'asset', - Cell: (cellProps: CellProps) => ( - - - {cellProps.row.original.marketShortName} - - - ), - width: 50, - }, - { - Header: {t('leaderboard.trader-history.table.status')}, - accessor: 'status', - Cell: (cellProps: CellProps) => { - return {cellProps.row.original.status}; - }, - width: 30, - }, - { - Header: ( - {t('leaderboard.trader-history.table.total-pnl')} - ), - accessor: 'pnl', - Cell: (cellProps: CellProps) => ( - - - - {cellProps.row.original.pnlPct} - - - ), - width: 40, - sortType: 'basic', - sortable: true, - }, - ], - }, - ]} - /> - - - ); -}; - -const StyledTable = styled(Table)<{ compact: boolean | undefined }>` - margin-top: ${({ compact }) => (compact ? '0' : '15px')}; -`; - -const TableTitle = styled.div` - width: 100%; - display: flex; - justify-content: flex-start; -`; - -const TitleText = styled.a` - font-family: ${(props) => props.theme.fonts.regular}; - color: ${(props) => props.theme.colors.selectedTheme.gray}; - - &:hover { - text-decoration: underline; - cursor: pointer; - } -`; - -const StyledCell = styled.div` - color: ${(props) => props.theme.colors.selectedTheme.button.text.primary}; - display: flex; -`; - -const TitleSeparator = styled.div` - margin-left: 10px; - margin-right: 10px; - font-family: ${(props) => props.theme.fonts.regular}; - color: ${(props) => props.theme.colors.selectedTheme.gray}; -`; - -const TraderText = styled.a` - font-family: ${(props) => props.theme.fonts.regular}; - color: ${(props) => props.theme.colors.selectedTheme.button.text.primary}; - - &:hover { - text-decoration: underline; - } -`; - -const TableHeader = styled.div` - font-family: ${(props) => props.theme.fonts.regular}; - color: ${(props) => props.theme.colors.selectedTheme.gray}; -`; - -const StyledCurrencyIcon = styled(CurrencyIcon)` - width: 30px; - height: 30px; - margin-right: 5px; -`; - -const CurrencyInfo = styled(FlexDiv)` - align-items: center; -`; - -const StyledSubtitle = styled.div` - font-family: ${(props) => props.theme.fonts.regular}; - font-size: 13px; - color: ${(props) => props.theme.colors.selectedTheme.button.text.primary}; - text-transform: capitalize; -`; - -const PnlContainer = styled.div` - display: flex; - flex-direction: column; - align-items: center; -`; - -const ColorCodedPrice = styled(Currency.Price)` - align-items: right; - color: ${(props) => - props.price > 0 - ? props.theme.colors.selectedTheme.green - : props.price < 0 - ? props.theme.colors.selectedTheme.red - : props.theme.colors.selectedTheme.button.text.primary}; -`; - -const StyledValue = styled.div` - font-family: ${(props) => props.theme.fonts.mono}; - font-size: 13px; - color: ${(props) => - props.color === 'green' - ? props.theme.colors.selectedTheme.green - : props.color === 'red' - ? props.theme.colors.selectedTheme.red - : props.theme.colors.selectedTheme.button.text.primary}; - margin: 0; - text-align: end; -`; - -const StyledFuturesIcon = styled(FuturesIcon)` - margin-left: 5px; -`; - -export default TraderHistory; diff --git a/sections/leaderboard/TraderHistory/index.tsx b/sections/leaderboard/TraderHistory/index.tsx deleted file mode 100644 index 5564828bc7..0000000000 --- a/sections/leaderboard/TraderHistory/index.tsx +++ /dev/null @@ -1 +0,0 @@ -export { default } from './TraderHistory'; diff --git a/sections/leaderboard/common.tsx b/sections/leaderboard/common.tsx deleted file mode 100644 index 40d99d6cde..0000000000 --- a/sections/leaderboard/common.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import styled from 'styled-components'; - -export type Tier = 'gold' | 'silver' | 'bronze' | null; -export type CompetitionRound = '1' | '2' | null; - -export const getMedal = (position: number) => { - switch (position) { - case 1: - return 🥇; - case 2: - return 🥈; - case 3: - return 🥉; - } -}; - -export const COMPETITION_TIERS: Tier[] = ['bronze', 'silver', 'gold']; - -export const PIN = ' 📌'; - -const Medal = styled.span` - font-size: 16px; - margin-left: 4px; -`; - -export const StyledTrader = styled.a` - color: ${(props) => props.theme.colors.selectedTheme.button.text.primary}; - display: flex; - - &:hover { - text-decoration: underline; - cursor: pointer; - } -`; diff --git a/sections/leaderboard/medal.ts b/sections/leaderboard/medal.ts new file mode 100644 index 0000000000..00aacff2d3 --- /dev/null +++ b/sections/leaderboard/medal.ts @@ -0,0 +1,6 @@ +import styled from 'styled-components'; + +export const Medal = styled.span` + font-size: 16px; + margin-left: 4px; +`; diff --git a/sections/leaderboard/trader.ts b/sections/leaderboard/trader.ts new file mode 100644 index 0000000000..5f1f89ba34 --- /dev/null +++ b/sections/leaderboard/trader.ts @@ -0,0 +1,11 @@ +import styled from 'styled-components'; + +export const StyledTrader = styled.a` + color: ${(props) => props.theme.colors.selectedTheme.button.text.primary}; + display: flex; + + &:hover { + text-decoration: underline; + cursor: pointer; + } +`; diff --git a/sections/shared/Layout/AppLayout/AppLayout.tsx b/sections/shared/Layout/AppLayout/AppLayout.tsx index b8e269cb14..6c851ad2b7 100644 --- a/sections/shared/Layout/AppLayout/AppLayout.tsx +++ b/sections/shared/Layout/AppLayout/AppLayout.tsx @@ -1,4 +1,4 @@ -import { FC } from 'react'; +import { FC, memo } from 'react'; import { DesktopOnlyView, MobileOrTabletView } from 'components/Media'; import NotificationContainer from 'constants/NotificationContainer'; @@ -12,7 +12,7 @@ type AppLayoutProps = { children: React.ReactNode; }; -const AppLayout: FC = ({ children }) => ( +const AppLayout: FC = memo(({ children }) => ( @@ -28,6 +28,6 @@ const AppLayout: FC = ({ children }) => ( -); +)); export default AppLayout; diff --git a/sections/shared/Layout/AppLayout/GitHashID/GitHashID.tsx b/sections/shared/Layout/AppLayout/GitHashID.tsx similarity index 100% rename from sections/shared/Layout/AppLayout/GitHashID/GitHashID.tsx rename to sections/shared/Layout/AppLayout/GitHashID.tsx diff --git a/sections/shared/Layout/AppLayout/GitHashID/index.ts b/sections/shared/Layout/AppLayout/GitHashID/index.ts deleted file mode 100644 index 55569aeaf0..0000000000 --- a/sections/shared/Layout/AppLayout/GitHashID/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './GitHashID'; diff --git a/sections/shared/Layout/AppLayout/Header/BalanceActions.tsx b/sections/shared/Layout/AppLayout/Header/BalanceActions.tsx index 3ec75a92ce..ded5d194db 100644 --- a/sections/shared/Layout/AppLayout/Header/BalanceActions.tsx +++ b/sections/shared/Layout/AppLayout/Header/BalanceActions.tsx @@ -1,11 +1,12 @@ import { useRouter } from 'next/router'; -import { FC, useCallback, useEffect, useMemo, useState } from 'react'; +import { FC, memo, useCallback, useEffect, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { components } from 'react-select'; -import styled, { useTheme } from 'styled-components'; +import styled from 'styled-components'; import Button from 'components/Button'; import CurrencyIcon from 'components/Currency/CurrencyIcon'; +import { FlexDivRow, FlexDivRowCentered } from 'components/layout/flex'; import Select from 'components/Select'; import { FuturesAccountTypes } from 'queries/futures/types'; import { FuturesPosition } from 'sdk/types/futures'; @@ -17,7 +18,6 @@ import { selectIsolatedMarginPositions, } from 'state/futures/selectors'; import { useAppSelector, useAppDispatch } from 'state/hooks'; -import { FlexDivRow, FlexDivRowCentered } from 'styles/common'; import { zeroBN, formatDollars } from 'utils/formatters/number'; import { getMarketName, MarketKeyByAsset } from 'utils/futures'; @@ -28,10 +28,38 @@ type ReactSelectOptionProps = { onClick?: () => {}; }; +const GetUsdButton = memo(() => { + const { t } = useTranslation(); + const router = useRouter(); + + return ( + router.push(`/exchange/?quote=sUSD`)}> + {t('header.balance.get-more-susd')} + + ); +}); + +const Group: FC = memo(({ children, ...props }) => ( + + {children} + + +)); + +const NoOptionsMessage: FC = memo((props) => { + const { t } = useTranslation(); + + return ( + + {t('header.balance.no-accessible-margin')} + + + ); +}); + const BalanceActions: FC = () => { const [balanceLabel, setBalanceLabel] = useState(''); const { t } = useTranslation(); - const theme = useTheme(); const router = useRouter(); const crossPositions = useAppSelector(selectCrossMarginPositions); @@ -41,22 +69,20 @@ const BalanceActions: FC = () => { const dispatch = useAppDispatch(); const setMarketConfig = useCallback( - (position: FuturesPosition, accountType: FuturesAccountTypes): ReactSelectOptionProps => { - return { - label: getMarketName(position.asset), - synthIcon: MarketKeyByAsset[position.asset], - marketRemainingMargin: formatDollars(position.remainingMargin), - onClick: () => { - // TODO: Remove eventually - dispatch(setFuturesAccountType(accountType)); - return router.push(`/market/?asset=${position.asset}&accountType=${accountType}`); - }, - }; - }, + (position: FuturesPosition, accountType: FuturesAccountTypes) => ({ + label: getMarketName(position.asset), + synthIcon: MarketKeyByAsset[position.asset], + marketRemainingMargin: formatDollars(position.remainingMargin), + onClick: () => { + // TODO: Remove eventually + dispatch(setFuturesAccountType(accountType)); + return router.push(`/market/?asset=${position.asset}&accountType=${accountType}`); + }, + }), [dispatch, router] ); - const OPTIONS = useMemo(() => { + const options = useMemo(() => { const isolatedPositionsFiltered = isolatedPositions .filter((position) => position.remainingMargin.gt(zeroBN)) .map((position) => setMarketConfig(position, FuturesAccountTypes.ISOLATED_MARGIN)); @@ -75,16 +101,14 @@ const BalanceActions: FC = () => { const OptionsGroupLabel: FC<{ label: string; totalAvailableMargin?: string }> = ({ label, totalAvailableMargin, - }) => { - return ( - - {t(label)} - {totalAvailableMargin} - - ); - }; + }) => ( + + {t(label)} + {totalAvailableMargin} + + ); - const formatOptionLabel = ({ + const formatOptionLabel: FC = ({ label, synthIcon, marketRemainingMargin, @@ -93,34 +117,12 @@ const BalanceActions: FC = () => { {synthIcon && } - {t(label)} + {t(label)} {marketRemainingMargin} ); - const GetUsdButton = () => ( - router.push(`/exchange/?quote=sUSD`)}> - {t('header.balance.get-more-susd')} - - ); - - const Group: FC = ({ children, ...props }) => ( - - {children} - - - ); - - const NoOptionsMessage: FC = (props) => { - return ( - - {t('header.balance.no-accessible-margin')} - - - ); - }; - useEffect(() => { setBalanceLabel(formatDollars(susdWalletBalance, { sign: '$' })); }, [balanceLabel, susdWalletBalance]); @@ -131,13 +133,14 @@ const BalanceActions: FC = () => { return ( - {susdWalletBalance.eq(zeroBN) && OPTIONS.length === 0 ? ( + {susdWalletBalance.eq(zeroBN) && options.length === 0 ? ( router.push(`/exchange/?quote=sUSD`)} noOutline + mono > - + {t('header.balance.get-susd')} ) : ( @@ -145,12 +148,11 @@ const BalanceActions: FC = () => { formatOptionLabel={formatOptionLabel} formatGroupLabel={OptionsGroupLabel} controlHeight={41} - options={OPTIONS} + options={options} value={{ label: balanceLabel, synthIcon: 'sUSD' }} menuWidth={290} maxMenuHeight={500} - optionPadding={'0px'} //override default padding to 0 - optionBorderBottom={theme.colors.selectedTheme.border} + optionPadding="0px" components={{ Group, NoOptionsMessage, @@ -159,7 +161,7 @@ const BalanceActions: FC = () => { }} isSearchable={false} variant="flat" - > + /> )} ); @@ -198,6 +200,10 @@ const BalanceSelect = styled(Select)<{ value: { label: string } }>` .react-select__menu-notice--no-options { padding: 15px; } + + .react-select__option { + border-bottom: ${(props) => props.theme.colors.selectedTheme.border}; + } `; const StyledOptions = styled.div` @@ -211,7 +217,7 @@ const StyledCurrencyIcon = styled(CurrencyIcon)` width: 20px; `; -const StyledLabel = styled.div<{ noPadding: boolean }>` +const StyledLabel = styled.div` white-space: nowrap; `; @@ -236,7 +242,6 @@ const StyledButton = styled(Button)` const StyledWidgetButton = styled(Button)` height: 41px; font-size: 13px; - font-family: ${(props) => props.theme.fonts.mono}; padding: 10px; white-space: nowrap; display: flex; diff --git a/sections/shared/Layout/AppLayout/Header/ConnectionDot.tsx b/sections/shared/Layout/AppLayout/Header/ConnectionDot.tsx index 24c4d19626..25fcf46707 100644 --- a/sections/shared/Layout/AppLayout/Header/ConnectionDot.tsx +++ b/sections/shared/Layout/AppLayout/Header/ConnectionDot.tsx @@ -46,6 +46,7 @@ const Dot = styled.span<{ background: string }>` height: 8px; border-radius: 100%; background-color: ${(props) => props.background}; + margin-right: 6px; `; export default ConnectionDot; diff --git a/sections/shared/Layout/AppLayout/Header/MobileUserMenu/MobileMenuModal.tsx b/sections/shared/Layout/AppLayout/Header/MobileUserMenu/MobileMenuModal.tsx index 548729c199..8c87b48016 100644 --- a/sections/shared/Layout/AppLayout/Header/MobileUserMenu/MobileMenuModal.tsx +++ b/sections/shared/Layout/AppLayout/Header/MobileUserMenu/MobileMenuModal.tsx @@ -13,7 +13,7 @@ import Logo from 'sections/shared/Layout/Logo'; import { currentThemeState } from 'store/ui'; import { HOMEPAGE_MENU_LINKS, MOBILE_NAV_LINKS } from '../constants'; -import { MenuButton } from './common'; +import { MenuButton } from './menu'; import MobileSubMenu from './MobileSubMenu'; type MobileMenuModalProps = { diff --git a/sections/shared/Layout/AppLayout/Header/MobileUserMenu/MobileSettingsModal.tsx b/sections/shared/Layout/AppLayout/Header/MobileUserMenu/MobileSettingsModal.tsx index b084952eaf..9b9d3fce01 100644 --- a/sections/shared/Layout/AppLayout/Header/MobileUserMenu/MobileSettingsModal.tsx +++ b/sections/shared/Layout/AppLayout/Header/MobileUserMenu/MobileSettingsModal.tsx @@ -14,6 +14,7 @@ import MoonIcon from 'assets/svg/app/moon.svg'; import SunIcon from 'assets/svg/app/sun.svg'; import FullScreenModal from 'components/FullScreenModal'; import { EXTERNAL_LINKS } from 'constants/links'; +import { languageIcon } from 'constants/menu'; import ROUTES from 'constants/routes'; import usePersistedRecoilState from 'hooks/usePersistedRecoilState'; import Logo from 'sections/shared/Layout/Logo'; @@ -21,7 +22,6 @@ import { languageState } from 'store/app'; import { currentThemeState } from 'store/ui'; import colors from 'styles/theme/colors'; -import { languageIcon } from './common'; import MobileSubMenu from './MobileSubMenu'; type MobileSettingsModalProps = { diff --git a/sections/shared/Layout/AppLayout/Header/MobileUserMenu/MobileSubMenu.tsx b/sections/shared/Layout/AppLayout/Header/MobileUserMenu/MobileSubMenu.tsx index b93f9462f4..57b7895bef 100644 --- a/sections/shared/Layout/AppLayout/Header/MobileUserMenu/MobileSubMenu.tsx +++ b/sections/shared/Layout/AppLayout/Header/MobileUserMenu/MobileSubMenu.tsx @@ -1,5 +1,6 @@ import Link from 'next/link'; import { useRouter } from 'next/router'; +import { memo } from 'react'; import { useTranslation } from 'react-i18next'; import { useRecoilValue } from 'recoil'; import styled, { css } from 'styled-components'; @@ -12,7 +13,7 @@ import { currentThemeState } from 'store/ui'; import { ThemeName } from 'styles/theme'; import { SubMenuLink } from '../constants'; -import { MenuButton } from './common'; +import { MenuButton } from './menu'; type MobileSubMenuOption = { label: string; @@ -32,71 +33,64 @@ type MobileSubMenuProps = { onToggle(): void; }; -const MobileSubMenu: React.FC = ({ - i18nLabel, - active, - options, - links, - onDismiss, - onToggle, -}) => { - const { t } = useTranslation(); - const { asPath } = useRouter(); - - const currentTheme = useRecoilValue(currentThemeState); - - return ( - <> - - {t(i18nLabel)} - {active ? : } - - {active && ( - - {links - ? links.map(({ i18nLabel, link: subLink, badge }) => ( - - · - - -
- {t(i18nLabel)}{' '} - {badge && - badge.map(({ i18nLabel, color }) => ( +const MobileSubMenu: React.FC = memo( + ({ i18nLabel, active, options, links, onDismiss, onToggle }) => { + const { t } = useTranslation(); + const { asPath } = useRouter(); + const currentTheme = useRecoilValue(currentThemeState); + + return ( + <> + + {t(i18nLabel)} + {active ? : } + + {active && ( + + {links + ? links.map(({ i18nLabel, link: subLink, badge }) => ( + + · + + +
+ {t(i18nLabel)}{' '} + {badge?.map(({ i18nLabel, color }) => ( {t(i18nLabel)} ))} -
-
-
-
- )) - : options?.map(({ label, icon, onClick, selected, externalLink }) => ( - - {icon ?? '·'} - {externalLink ? ( - - - {label} +
- - ) : ( - - - {label} - - - )} -
- ))} -
- )} - - ); -}; + + + )) + : options?.map(({ label, icon, onClick, selected, externalLink }) => ( + + {icon ?? '·'} + {externalLink ? ( + + + {label} + + + ) : ( + + + {label} + + + )} + + ))} + + )} + + ); + } +); const SubMenuButton = styled(MenuButton)` ${(props) => diff --git a/sections/shared/Layout/AppLayout/Header/MobileUserMenu/MobileUserMenu.tsx b/sections/shared/Layout/AppLayout/Header/MobileUserMenu/MobileUserMenu.tsx index c38b32af1f..4f92acf9c3 100644 --- a/sections/shared/Layout/AppLayout/Header/MobileUserMenu/MobileUserMenu.tsx +++ b/sections/shared/Layout/AppLayout/Header/MobileUserMenu/MobileUserMenu.tsx @@ -29,13 +29,7 @@ const MobileUserMenu: FC = () => { const toggleModal = (modal: 'menu' | 'settings') => () => { setIsOpen((s) => { if (!!s) { - if (s === modal) { - return undefined; - } else if (s === 'menu') { - return 'settings'; - } else { - return 'menu'; - } + return s === modal ? undefined : s === 'menu' ? 'settings' : 'menu'; } else { return modal; } diff --git a/sections/shared/Layout/AppLayout/Header/MobileUserMenu/MobileWalletActions.tsx b/sections/shared/Layout/AppLayout/Header/MobileUserMenu/MobileWalletActions.tsx index 09fa670eb4..2bf97f9dba 100644 --- a/sections/shared/Layout/AppLayout/Header/MobileUserMenu/MobileWalletActions.tsx +++ b/sections/shared/Layout/AppLayout/Header/MobileUserMenu/MobileWalletActions.tsx @@ -28,17 +28,13 @@ export const MobileWalletActions: FC = ({ toggleModal } {ensAvatar ? ( ) : ( - + )} {walletLabel} ); }; -const StyledConnectionDot = styled(ConnectionDot)` - margin-right: 6px; -`; - const StyledButton = styled(Button)` font-size: 13px; text-transform: lowercase; diff --git a/sections/shared/Layout/AppLayout/Header/MobileUserMenu/MobileWalletButton.tsx b/sections/shared/Layout/AppLayout/Header/MobileUserMenu/MobileWalletButton.tsx index ef6d0f41d4..527ff61aa3 100644 --- a/sections/shared/Layout/AppLayout/Header/MobileUserMenu/MobileWalletButton.tsx +++ b/sections/shared/Layout/AppLayout/Header/MobileUserMenu/MobileWalletButton.tsx @@ -16,13 +16,11 @@ type MobileWalletButtonProps = { closeModal(): void; }; -const MobileWalletButton: React.FC = ({ toggleModal }) => { +const MobileConnectButton = () => { const { t } = useTranslation(); - const { network, isWalletConnected } = Connector.useContainer(); const { openConnectModal: connectWallet } = useConnectModal(); - const { openChainModal } = useChainModal(); - const walletIsNotConnected = ( + return ( = ({ toggleModal }) data-testid="connect-wallet" mono > - + {t('common.wallet.connect-wallet')} ); +}; + +const MobileUnsupportedButton = () => { + const { t } = useTranslation(); + const { openChainModal } = useChainModal(); - const walletIsConnectedButNotSupported = ( + return ( = ({ toggleModal }) mono onClick={openChainModal} > - + {t('common.wallet.unsupported-network')} ); +}; - const walletIsConnectedAndSupported = ; +const MobileWalletButton: React.FC = ({ toggleModal }) => { + const { network, isWalletConnected } = Connector.useContainer(); - return isWalletConnected - ? isSupportedNetworkId(network?.id as NetworkId) - ? walletIsConnectedAndSupported - : walletIsConnectedButNotSupported - : walletIsNotConnected; + if (!isWalletConnected) { + return ; + } else if (isSupportedNetworkId(network?.id as NetworkId)) { + return ; + } else { + return ; + } }; -const StyledConnectionDot = styled(ConnectionDot)` - margin-right: 6px; -`; - const ConnectButton = styled(Button)` font-size: 13px; `; diff --git a/sections/shared/Layout/AppLayout/Header/MobileUserMenu/common.ts b/sections/shared/Layout/AppLayout/Header/MobileUserMenu/menu.ts similarity index 62% rename from sections/shared/Layout/AppLayout/Header/MobileUserMenu/common.ts rename to sections/shared/Layout/AppLayout/Header/MobileUserMenu/menu.ts index 54dd4a0e60..bfc3b2a980 100644 --- a/sections/shared/Layout/AppLayout/Header/MobileUserMenu/common.ts +++ b/sections/shared/Layout/AppLayout/Header/MobileUserMenu/menu.ts @@ -1,6 +1,5 @@ import styled, { css } from 'styled-components'; -import { EXTERNAL_LINKS } from 'constants/links'; import ROUTES from 'constants/routes'; import type { ThemeName } from 'styles/theme'; @@ -32,21 +31,3 @@ export const MenuButton = styled.div<{ } `} `; - -export const SUB_MENUS = { - [ROUTES.Dashboard.Overview]: [ - { label: 'Overview', link: '/dashboard/overview' }, - // { label: 'Positions', link: '/positions' }, - // { label: 'Rewards', link: '/rewards' }, - { label: 'Markets', link: '/dashboard/markets' }, - // { label: 'Governance', link: '/governance' }, - ], - [ROUTES.Home.Root]: [ - { label: 'Overview', link: EXTERNAL_LINKS.Docs.Governance }, - { label: 'KIPs', link: EXTERNAL_LINKS.Governance.Kips }, - ], -}; - -export const languageIcon = { - en: '🌐', -}; diff --git a/sections/shared/Layout/AppLayout/Header/Nav/Nav.tsx b/sections/shared/Layout/AppLayout/Header/Nav.tsx similarity index 86% rename from sections/shared/Layout/AppLayout/Header/Nav/Nav.tsx rename to sections/shared/Layout/AppLayout/Header/Nav.tsx index 393481c295..277e2a68d0 100644 --- a/sections/shared/Layout/AppLayout/Header/Nav/Nav.tsx +++ b/sections/shared/Layout/AppLayout/Header/Nav.tsx @@ -1,6 +1,6 @@ import Link from 'next/link'; import { useRouter } from 'next/router'; -import { FC, FunctionComponent } from 'react'; +import { FC, FunctionComponent, memo, useCallback } from 'react'; import { useTranslation } from 'react-i18next'; import styled from 'styled-components'; @@ -12,7 +12,7 @@ import { selectMarketAsset } from 'state/futures/selectors'; import { useAppSelector } from 'state/hooks'; import { linkCSS } from 'styles/common'; -import { DESKTOP_NAV_LINKS, Badge as BadgeType } from '../constants'; +import { DESKTOP_NAV_LINKS, Badge as BadgeType } from './constants'; type ReactSelectOptionProps = { i18nLabel: string; @@ -23,14 +23,17 @@ type ReactSelectOptionProps = { Icon: FunctionComponent; }; -const Nav: FC = () => { +const Nav: FC = memo(() => { const { t } = useTranslation(); const { asPath } = useRouter(); const marketAsset = useAppSelector(selectMarketAsset); - function getLink(link: string) { - return link.slice(0, 7) === '/market' ? `/market/?asset=${marketAsset}` : link; - } + const getLink = useCallback( + (link: string) => { + return link.indexOf('/market') === 0 ? `/market/?asset=${marketAsset}` : link; + }, + [marketAsset] + ); const formatOptionLabel = ({ i18nLabel, @@ -39,19 +42,22 @@ const Nav: FC = () => { link, isActive, }: ReactSelectOptionProps) => { - if (i18nLabel === 'header.nav.markets' || i18nLabel === 'header.nav.leaderboard') + if (i18nLabel === 'header.nav.markets' || i18nLabel === 'header.nav.leaderboard') { return ( {t(i18nLabel)} ); + } + return ( {t(i18nLabel)} - {badge && - badge.map(({ i18nLabel, color }) => {t(i18nLabel)})} + {badge?.map(({ i18nLabel, color }) => ( + {t(i18nLabel)} + ))} {Icon && } @@ -66,17 +72,13 @@ const Nav: FC = () => { const routeBase = asPath.split('/')[1]; const linkBase = link.split('/')[1]?.split('?')[0]; const isActive = routeBase === linkBase; - const url = getLink(link); + if (!links) { return ( - + + {t(i18nLabel)} + ); } @@ -97,7 +99,7 @@ const Nav: FC = () => { ); -}; +}); const MenuLinks = styled.ul` display: flex; diff --git a/sections/shared/Layout/AppLayout/Header/Nav/index.ts b/sections/shared/Layout/AppLayout/Header/Nav/index.ts deleted file mode 100644 index 13fa327162..0000000000 --- a/sections/shared/Layout/AppLayout/Header/Nav/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './Nav'; diff --git a/sections/shared/Layout/AppLayout/Header/NetworksSwitcher.tsx b/sections/shared/Layout/AppLayout/Header/NetworksSwitcher.tsx index 6ffa9f1d9b..b25f262719 100644 --- a/sections/shared/Layout/AppLayout/Header/NetworksSwitcher.tsx +++ b/sections/shared/Layout/AppLayout/Header/NetworksSwitcher.tsx @@ -28,8 +28,8 @@ type ReactSelectOptionProps = { const NetworksSwitcher: FC = () => { const { network: activeChain } = Connector.useContainer(); - const { openChainModal } = useChainModal(); const { t } = useTranslation(); + const { openChainModal } = useChainModal(); const isL2 = useIsL2(); const network = activeChain?.id === chain.optimismGoerli.id ? 'testnet' : 'mainnet'; const networkLabel = 'header.networks-switcher.optimism-' + network; @@ -95,11 +95,11 @@ const NetworksSwitcher: FC = () => { options={OPTIMISM_OPTIONS} value={{ label: networkLabel, prefixIcon: 'Optimism' }} menuWidth={240} - optionPadding={'0px'} //override default padding to 0 + optionPadding="0px" components={{ IndicatorSeparator, DropdownIndicator }} isSearchable={false} variant="flat" - > + />
); }; diff --git a/sections/shared/Layout/AppLayout/Header/WalletActions.tsx b/sections/shared/Layout/AppLayout/Header/WalletActions.tsx index 96ce5c861f..65ffc17cea 100644 --- a/sections/shared/Layout/AppLayout/Header/WalletActions.tsx +++ b/sections/shared/Layout/AppLayout/Header/WalletActions.tsx @@ -1,5 +1,5 @@ import { useAccountModal } from '@rainbow-me/rainbowkit'; -import { FC, useEffect, useState } from 'react'; +import { FC, useMemo } from 'react'; import styled, { css } from 'styled-components'; import { useEnsAvatar, useEnsName } from 'wagmi'; @@ -18,12 +18,11 @@ export const WalletActions: FC = ({ isMobile }) => { const { data: ensAvatar } = useEnsAvatar({ address: walletAddress!, chainId: 1 }); const { data: ensName } = useEnsName({ address: walletAddress!, chainId: 1 }); - const [walletLabel, setWalletLabel] = useState(''); const truncatedWalletAddress = truncateAddress(walletAddress ?? ''); const { openAccountModal } = useAccountModal(); - useEffect(() => { - setWalletLabel(ensName || truncatedWalletAddress!); + const walletLabel = useMemo(() => { + return ensName || truncatedWalletAddress!; }, [ensName, truncatedWalletAddress]); return ( @@ -45,7 +44,7 @@ export const WalletActions: FC = ({ isMobile }) => { style={{ borderRadius: '50%', marginRight: '8px' }} /> ) : ( - + )} {walletLabel} @@ -53,10 +52,6 @@ export const WalletActions: FC = ({ isMobile }) => { ); }; -const StyledConnectionDot = styled(ConnectionDot)` - margin-right: 6px; -`; - const Container = styled.div<{ isMobile?: boolean }>` font-size: 12px; font-family: ${(props) => props.theme.fonts.mono}; diff --git a/sections/shared/Layout/AppLayout/Header/WalletButtons.tsx b/sections/shared/Layout/AppLayout/Header/WalletButtons.tsx index 093bcdb30d..45d4967723 100644 --- a/sections/shared/Layout/AppLayout/Header/WalletButtons.tsx +++ b/sections/shared/Layout/AppLayout/Header/WalletButtons.tsx @@ -42,7 +42,7 @@ const WalletButtons: React.FC = () => { data-testid="connect-wallet" mono > - + {t('common.wallet.connect-wallet')} @@ -54,7 +54,7 @@ const WalletButtons: React.FC = () => { {t('homepage.l2.cta-buttons.switch-networks')} - + {t('common.wallet.unsupported-network')} @@ -88,10 +88,6 @@ const Container = styled.div` grid-auto-flow: column; `; -const StyledConnectionDot = styled(ConnectionDot)` - margin-right: 6px; -`; - const MenuButton = styled(Button)` display: grid; place-items: center; diff --git a/sections/shared/Layout/HomeLayout/Background.tsx b/sections/shared/Layout/HomeLayout/Background.tsx index abf949e8b1..d69559b29a 100644 --- a/sections/shared/Layout/HomeLayout/Background.tsx +++ b/sections/shared/Layout/HomeLayout/Background.tsx @@ -1,7 +1,7 @@ -import React from 'react'; +import { memo } from 'react'; import styled, { keyframes } from 'styled-components'; -const Background = () => { +const Background = memo(() => { return (
@@ -9,7 +9,7 @@ const Background = () => {
); -}; +}); const drop = keyframes` from { @@ -19,6 +19,7 @@ const drop = keyframes` top:100%; } `; + const Container = styled.div` background-color: transparent; width: 100vw; diff --git a/sections/shared/Layout/HomeLayout/Banner.tsx b/sections/shared/Layout/HomeLayout/Banner.tsx index 9c2ae0018d..6e1d14787c 100644 --- a/sections/shared/Layout/HomeLayout/Banner.tsx +++ b/sections/shared/Layout/HomeLayout/Banner.tsx @@ -1,17 +1,13 @@ +import { memo } from 'react'; import styled from 'styled-components'; import { DesktopOnlyView, MobileOrTabletView } from 'components/Media'; import { BANNER_ENABLED, BANNER_LINK_URL, BANNER_TEXT } from 'constants/announcement'; import media from 'styles/media'; -const Banner = () => { +const Banner = memo(() => { if (!BANNER_ENABLED) return null; - const linkProps = BANNER_LINK_URL - ? { href: BANNER_LINK_URL, target: '_blank' } - : { as: 'p' as const }; - const bannerLink = {BANNER_TEXT}; - return ( <> @@ -24,7 +20,7 @@ const Banner = () => { ); -}; +}); const FuturesLink = styled.a` margin-right: 5px; @@ -33,6 +29,12 @@ const FuturesLink = styled.a` border-radius: 20px; `; +const linkProps = BANNER_LINK_URL + ? { href: BANNER_LINK_URL, target: '_blank' } + : { as: 'p' as const }; + +const bannerLink = {BANNER_TEXT}; + const FuturesBannerContainer = styled.div` height: 70px; width: 100%; @@ -42,12 +44,9 @@ const FuturesBannerContainer = styled.div` ${media.lessThan('md')` position: relative; - width: 100%; - display: flex; margin-bottom: 0px; flex-direction: column; justify-content: center; - align-items: center; text-align: center; background: transaparent; padding: 22px 10px; diff --git a/sections/shared/Layout/HomeLayout/Footer.tsx b/sections/shared/Layout/HomeLayout/Footer.tsx index 27ec35d749..62eb9b806d 100644 --- a/sections/shared/Layout/HomeLayout/Footer.tsx +++ b/sections/shared/Layout/HomeLayout/Footer.tsx @@ -1,20 +1,21 @@ -import React from 'react'; +import { memo } from 'react'; import { useTranslation } from 'react-i18next'; import styled, { ThemeProvider } from 'styled-components'; import TwitterLogo from 'assets/svg/marketing/twitter-icon.svg'; import DiscordLogo from 'assets/svg/social/discord.svg'; import MirrorLogo from 'assets/svg/social/mirror.svg'; +import { GridContainer } from 'sections/homepage/section'; +import { FlexDivCentered } from 'components/layout/flex'; import PoweredBySynthetix from 'components/PoweredBySynthetix'; import { EXTERNAL_LINKS } from 'constants/links'; -import { GridContainer } from 'sections/homepage/common'; -import { FlexDivCentered, ExternalLink } from 'styles/common'; +import { ExternalLink } from 'styles/common'; import media from 'styles/media'; import { themes } from 'styles/theme'; import Logo from '../Logo'; -const Footer: React.FC = () => { +const Footer = memo(() => { const { t } = useTranslation(); const DOC_LINKS = [ { @@ -97,7 +98,7 @@ const Footer: React.FC = () => { }, ]; return ( - + @@ -132,7 +133,7 @@ const Footer: React.FC = () => { ); -}; +}); const StyledLink = styled.a` cursor: pointer; diff --git a/sections/shared/Layout/HomeLayout/Header.tsx b/sections/shared/Layout/HomeLayout/Header.tsx index 01520ad5a4..f342c18a13 100644 --- a/sections/shared/Layout/HomeLayout/Header.tsx +++ b/sections/shared/Layout/HomeLayout/Header.tsx @@ -1,6 +1,6 @@ import Link from 'next/link'; import router from 'next/router'; -import { FC, useMemo } from 'react'; +import { useMemo, memo } from 'react'; import { useTranslation } from 'react-i18next'; import styled from 'styled-components'; @@ -10,18 +10,19 @@ import TwitterLogo from 'assets/svg/marketing/twitter-icon.svg'; import DiscordLogo from 'assets/svg/social/discord.svg'; import MirrorLogo from 'assets/svg/social/mirror.svg'; import Button from 'components/Button'; +import { FlexDivRow, FlexDivRowCentered } from 'components/layout/flex'; +import { GridDivCenteredCol } from 'components/layout/grid'; import { MobileHiddenView, MobileOnlyView } from 'components/Media'; import { DEFAULT_FUTURES_MARGIN_TYPE } from 'constants/defaults'; import { EXTERNAL_LINKS } from 'constants/links'; import ROUTES from 'constants/routes'; -import { FlexDivRow, FlexDivRowCentered, GridDivCenteredCol } from 'styles/common'; import MobileUserMenu from '../AppLayout/Header/MobileUserMenu'; import Logo from '../Logo'; export type TPages = 'landing-page' | 'stats-page'; -const Header: FC = () => { +const Header = memo(() => { const { t } = useTranslation(); const LINKS = useMemo( @@ -59,7 +60,6 @@ const Header: FC = () => { onClick: () => window.open(EXTERNAL_LINKS.Docs.DocsRoot, '_blank'), }, ], - // eslint-disable-next-line [t] ); @@ -148,7 +148,7 @@ const Header: FC = () => { ); -}; +}); const MobileContainer = styled(FlexDivRow)` justify-content: center; diff --git a/sections/shared/Layout/HomeLayout/HomeLayout.tsx b/sections/shared/Layout/HomeLayout/HomeLayout.tsx index 6e9bb2760c..7f898bf49f 100644 --- a/sections/shared/Layout/HomeLayout/HomeLayout.tsx +++ b/sections/shared/Layout/HomeLayout/HomeLayout.tsx @@ -16,7 +16,7 @@ type HomeLayoutProps = { }; const HomeLayout: FC = ({ children }) => ( - + diff --git a/sections/shared/Layout/Logo/Logo.tsx b/sections/shared/Layout/Logo.tsx similarity index 88% rename from sections/shared/Layout/Logo/Logo.tsx rename to sections/shared/Layout/Logo.tsx index 661ec06a39..016cf3ba7c 100644 --- a/sections/shared/Layout/Logo/Logo.tsx +++ b/sections/shared/Layout/Logo.tsx @@ -1,5 +1,5 @@ import Link from 'next/link'; -import { FC } from 'react'; +import { FC, memo } from 'react'; import { useRecoilValue } from 'recoil'; import styled from 'styled-components'; @@ -8,7 +8,7 @@ import LogoSvg from 'assets/svg/brand/logo.svg'; import ROUTES from 'constants/routes'; import { currentThemeState } from 'store/ui'; -const SvgLogo = () => { +const SvgLogo = memo(() => { const currentTheme = useRecoilValue(currentThemeState); if (window.location.pathname === ROUTES.Home.Root) { @@ -20,9 +20,9 @@ const SvgLogo = () => { } return ; -}; +}); -const Logo: FC = () => { +const Logo: FC = memo(() => { return ( @@ -30,7 +30,7 @@ const Logo: FC = () => { ); -}; +}); const LogoContainer = styled.span` display: flex; diff --git a/sections/shared/Layout/Logo/index.ts b/sections/shared/Layout/Logo/index.ts deleted file mode 100644 index a5be7785e1..0000000000 --- a/sections/shared/Layout/Logo/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './Logo'; diff --git a/sections/shared/SystemStatus/SystemStatus.tsx b/sections/shared/SystemStatus.tsx similarity index 94% rename from sections/shared/SystemStatus/SystemStatus.tsx rename to sections/shared/SystemStatus.tsx index 368be0aed3..17ad440504 100644 --- a/sections/shared/SystemStatus/SystemStatus.tsx +++ b/sections/shared/SystemStatus.tsx @@ -8,16 +8,12 @@ import SystemDownIcon from 'assets/svg/app/system-down.svg'; import DiscordIcon from 'assets/svg/social/discord.svg'; import GithubIcon from 'assets/svg/social/github.svg'; import TwitterIcon from 'assets/svg/social/twitter.svg'; +import { FlexDivColCentered } from 'components/layout/flex'; +import { GridDivCenteredCol } from 'components/layout/grid'; import { EXTERNAL_LINKS, PROD_HOSTNAME } from 'constants/links'; import { HEADER_HEIGHT } from 'constants/ui'; import Logo from 'sections/shared/Layout/Logo'; -import { - FlexDivColCentered, - PageContent, - FullScreenContainer, - ExternalLink, - GridDivCenteredCol, -} from 'styles/common'; +import { PageContent, FullScreenContainer, ExternalLink } from 'styles/common'; import media from 'styles/media'; type SystemStatusProps = { diff --git a/sections/shared/SystemStatus/index.ts b/sections/shared/SystemStatus/index.ts deleted file mode 100644 index fa51f4e496..0000000000 --- a/sections/shared/SystemStatus/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './SystemStatus'; diff --git a/sections/shared/components/CompetitionBanner/CompetitionBanner.tsx b/sections/shared/components/CompetitionBanner.tsx similarity index 77% rename from sections/shared/components/CompetitionBanner/CompetitionBanner.tsx rename to sections/shared/components/CompetitionBanner.tsx index 519a24f977..fb96c4c19f 100644 --- a/sections/shared/components/CompetitionBanner/CompetitionBanner.tsx +++ b/sections/shared/components/CompetitionBanner.tsx @@ -1,8 +1,9 @@ -import React, { FC } from 'react'; +import { memo, FC } from 'react'; import { useTranslation } from 'react-i18next'; import styled from 'styled-components'; import CompetitionBannerBg from 'assets/svg/app/competition-banner-bg.svg'; +import * as Text from 'components/Text'; import { COMPETITION_DATES, COMPETITION_ENABLED } from 'constants/competition'; import { EXTERNAL_LINKS } from 'constants/links'; import { ExternalLink } from 'styles/common'; @@ -16,19 +17,15 @@ type CompetitionBannerProps = { hideBanner?: boolean; }; -export const CompetitionBanner: FC = ({ - compact, - hideBanner, -}: CompetitionBannerProps) => { +const formatedStartDate = formatDateWithoutYear(COMPETITION_DATES.START_DATE); +const formatedEndDate = formatDateWithoutYear(COMPETITION_DATES.END_DATE); +const competitionPeriod = `${formatedStartDate}-${formatedEndDate.split(' ')[1]}`; + +export const CompetitionBanner: FC = memo(({ compact, hideBanner }) => { const { t } = useTranslation(); if (!COMPETITION_ENABLED) return null; - const formatedStartDate = formatDateWithoutYear(COMPETITION_DATES.START_DATE); - const formatedEndDate = formatDateWithoutYear(COMPETITION_DATES.END_DATE); - - const competitionPeriod = `${formatedStartDate}-${formatedEndDate.split(' ')[1]}`; - return ( {competitionPeriod} @@ -38,12 +35,9 @@ export const CompetitionBanner: FC = ({ ); -}; +}); -const BannerContainer = styled.div<{ - compact: boolean | undefined; - hideBanner: boolean | undefined; -}>` +const BannerContainer = styled.div<{ compact?: boolean; hideBanner?: boolean }>` position: relative; width: 100%; display: ${({ hideBanner }) => (hideBanner ? 'none' : 'flex')}; @@ -62,13 +56,11 @@ const BannerContainer = styled.div<{ gap: 10px; `; -const CompetitionPeriod = styled.p` - font-family: ${(props) => props.theme.fonts.monoBold}; +const CompetitionPeriod = styled(Text.Body).attrs({ mono: true, variant: 'bold' })` font-style: normal; font-size: 13px; line-height: 10px; color: ${(props) => props.theme.colors.selectedTheme.gray}; - // clear UA style. margin: 0; `; @@ -97,7 +89,7 @@ const StyledBg = styled(CompetitionBannerBg)` width: 100%; height: 100%; - // prevent background-image from covering the text. + /* prevent background-image from covering the text. */ z-index: -1; position: absolute; diff --git a/sections/shared/components/CompetitionBanner/index.ts b/sections/shared/components/CompetitionBanner/index.ts deleted file mode 100644 index 15de7a0688..0000000000 --- a/sections/shared/components/CompetitionBanner/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './CompetitionBanner'; diff --git a/sections/shared/components/CompetitionBanner/CompetitionState.tsx b/sections/shared/components/CompetitionState.tsx similarity index 98% rename from sections/shared/components/CompetitionBanner/CompetitionState.tsx rename to sections/shared/components/CompetitionState.tsx index d433424a62..62d2e1ef78 100644 --- a/sections/shared/components/CompetitionBanner/CompetitionState.tsx +++ b/sections/shared/components/CompetitionState.tsx @@ -12,7 +12,6 @@ const Container = styled.p` line-height: 25px; text-align: center; color: ${(props) => props.theme.colors.selectedTheme.competitionBanner.state.text}; - // clear UA style. margin: 0; `; diff --git a/sections/shared/components/FeeCostSummary/FeeCostSummary.tsx b/sections/shared/components/FeeCostSummary.tsx similarity index 96% rename from sections/shared/components/FeeCostSummary/FeeCostSummary.tsx rename to sections/shared/components/FeeCostSummary.tsx index e04f93d023..dd7b68467c 100644 --- a/sections/shared/components/FeeCostSummary/FeeCostSummary.tsx +++ b/sections/shared/components/FeeCostSummary.tsx @@ -2,11 +2,10 @@ import Wei from '@synthetixio/wei'; import { FC, memo } from 'react'; import { useTranslation } from 'react-i18next'; +import { SummaryItem, SummaryItemValue, SummaryItemLabel } from 'sections/exchange/summary'; import { NO_VALUE } from 'constants/placeholder'; import { formatDollars } from 'utils/formatters/number'; -import { SummaryItem, SummaryItemValue, SummaryItemLabel } from '../common'; - type FeeRateSummaryItemProps = { feeCost?: Wei; }; diff --git a/sections/shared/components/FeeCostSummary/index.ts b/sections/shared/components/FeeCostSummary/index.ts deleted file mode 100644 index 51251c5ef4..0000000000 --- a/sections/shared/components/FeeCostSummary/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './FeeCostSummary'; diff --git a/sections/shared/components/FeeRateSummary/FeeRateSummary.tsx b/sections/shared/components/FeeRateSummary.tsx similarity index 72% rename from sections/shared/components/FeeRateSummary/FeeRateSummary.tsx rename to sections/shared/components/FeeRateSummary.tsx index cecace59fa..c16a2b78cb 100644 --- a/sections/shared/components/FeeRateSummary/FeeRateSummary.tsx +++ b/sections/shared/components/FeeRateSummary.tsx @@ -3,14 +3,13 @@ import { useTranslation } from 'react-i18next'; import styled from 'styled-components'; import TimerIcon from 'assets/svg/app/timer.svg'; -import StyledTooltip from 'components/Tooltip/StyledTooltip'; +import { SummaryItem, SummaryItemValue, SummaryItemLabel } from 'sections/exchange/summary'; +import Tooltip from 'components/Tooltip/Tooltip'; import { NO_VALUE } from 'constants/placeholder'; import { selectExchangeFeeRateWei, selectBaseFeeRateWei } from 'state/exchange/selectors'; import { useAppSelector } from 'state/hooks'; import { formatPercent } from 'utils/formatters/number'; -import { SummaryItem, SummaryItemValue, SummaryItemLabel } from '../common'; - const FeeRateSummaryItem: FC = memo(() => { const { t } = useTranslation(); @@ -29,25 +28,23 @@ const FeeRateSummaryItem: FC = memo(() => { ? formatPercent(exchangeFeeRate, { minDecimals: 2 }) : NO_VALUE} - {!!exchangeFeeRate && !!baseFeeRate ? ( - exchangeFeeRate.sub(baseFeeRate).gt(0) ? ( - <> - + - - - - {formatPercent(exchangeFeeRate.sub(baseFeeRate), { - minDecimals: 2, - })} - - - - - - ) : null + {exchangeFeeRate.sub(baseFeeRate).gt(0) ? ( + <> + + + + + + {formatPercent(exchangeFeeRate.sub(baseFeeRate), { + minDecimals: 2, + })} + + + + + ) : null} @@ -79,7 +76,7 @@ export const DynamicFeeRateItem = styled.span` } `; -const CustomStyledTooltip = styled(StyledTooltip)` +const CustomStyledTooltip = styled(Tooltip)` width: 300px; padding: 0px 4px; text-align: center; diff --git a/sections/shared/components/FeeRateSummary/index.ts b/sections/shared/components/FeeRateSummary/index.ts deleted file mode 100644 index 53dd71b045..0000000000 --- a/sections/shared/components/FeeRateSummary/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './FeeRateSummary'; diff --git a/sections/shared/components/GasPriceSelect/GasPriceSelect.tsx b/sections/shared/components/GasPriceSelect.tsx similarity index 72% rename from sections/shared/components/GasPriceSelect/GasPriceSelect.tsx rename to sections/shared/components/GasPriceSelect.tsx index 55a12d01a1..7fea2bb36b 100644 --- a/sections/shared/components/GasPriceSelect/GasPriceSelect.tsx +++ b/sections/shared/components/GasPriceSelect.tsx @@ -4,6 +4,7 @@ import { FC, useMemo, memo } from 'react'; import { useTranslation } from 'react-i18next'; import { useRecoilValue } from 'recoil'; +import { SummaryItem, SummaryItemValue, SummaryItemLabel } from 'sections/exchange/summary'; import { NO_VALUE } from 'constants/placeholder'; import { parseGasPriceObject } from 'hooks/useGas'; import useIsL1 from 'hooks/useIsL1'; @@ -11,21 +12,21 @@ import useIsL2 from 'hooks/useIsL2'; import { customGasPriceState, gasSpeedState } from 'store/wallet'; import { formatNumber, formatDollars } from 'utils/formatters/number'; -import { SummaryItem, SummaryItemValue, SummaryItemLabel } from '../common'; - type GasPriceSelectProps = { gasPrices: GasPrices | undefined; transactionFee?: Wei | number | null; className?: string; }; -const GasPriceSelect: FC = memo(({ gasPrices, transactionFee, ...rest }) => { - const { t } = useTranslation(); +type GasPriceItemProps = { + gasPrices: GasPrices | undefined; + transactionFee?: Wei | number | null; +}; + +const GasPriceItem: FC = memo(({ gasPrices, transactionFee }) => { + const isL2 = useIsL2(); const gasSpeed = useRecoilValue(gasSpeedState); const customGasPrice = useRecoilValue(customGasPriceState); - const isL2 = useIsL2(); - const isMainnet = useIsL1(); - const formattedTransactionFee = useMemo(() => { return transactionFee ? formatDollars(transactionFee, { maxDecimals: 1 }) : NO_VALUE; }, [transactionFee]); @@ -33,18 +34,22 @@ const GasPriceSelect: FC = memo(({ gasPrices, transactionFe const hasCustomGasPrice = customGasPrice !== ''; const gasPrice = gasPrices ? parseGasPriceObject(gasPrices[gasSpeed]) : null; - const gasPriceItem = useMemo( - () => ( - - {isL2 - ? formattedTransactionFee - : `${formatNumber(hasCustomGasPrice ? +customGasPrice : gasPrice ?? 0, { - minDecimals: 2, - })} Gwei`} - - ), - [isL2, formattedTransactionFee, hasCustomGasPrice, customGasPrice, gasPrice] + if (!gasPrice) return <>{NO_VALUE}; + + return ( + + {isL2 + ? formattedTransactionFee + : `${formatNumber(hasCustomGasPrice ? +customGasPrice : gasPrice ?? 0, { + minDecimals: 2, + })} Gwei`} + ); +}); + +const GasPriceSelect: FC = memo(({ gasPrices, transactionFee, ...rest }) => { + const { t } = useTranslation(); + const isMainnet = useIsL1(); return ( @@ -53,7 +58,9 @@ const GasPriceSelect: FC = memo(({ gasPrices, transactionFe ? t('common.summary.gas-prices.max-fee') : t('common.summary.gas-prices.gas-price')} - {gasPrice != null ? gasPriceItem : NO_VALUE} + + + ); }); diff --git a/sections/shared/components/GasPriceSelect/index.ts b/sections/shared/components/GasPriceSelect/index.ts deleted file mode 100644 index 5a274f0fed..0000000000 --- a/sections/shared/components/GasPriceSelect/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './GasPriceSelect'; diff --git a/sections/shared/components/PriceCurrencySelect/PriceCurrencySelect.tsx b/sections/shared/components/PriceCurrencySelect/PriceCurrencySelect.tsx deleted file mode 100644 index e83e2d2d73..0000000000 --- a/sections/shared/components/PriceCurrencySelect/PriceCurrencySelect.tsx +++ /dev/null @@ -1,45 +0,0 @@ -import { useMemo, FC } from 'react'; - -import Select from 'components/Select'; -import Connector from 'containers/Connector'; -import usePersistedRecoilState from 'hooks/usePersistedRecoilState'; -import { priceCurrencyState, PRICE_CURRENCIES } from 'store/app'; - -export const PriceCurrencySelect: FC = () => { - const [priceCurrency, setPriceCurrency] = usePersistedRecoilState(priceCurrencyState); - - const { synthsMap, network } = Connector.useContainer(); - - const currencyOptions = useMemo(() => { - if (network != null && synthsMap != null) { - return PRICE_CURRENCIES.filter((currencyKey) => synthsMap![currencyKey]).map( - (currencyKey) => { - const synth = synthsMap![currencyKey]!; - return { label: synth.asset, value: synth }; - } - ); - } - return []; - }, [network, synthsMap]); - - return ( -