From 84b6325f91b17e3f1763279f47c012dbf55f4c3f Mon Sep 17 00:00:00 2001 From: heronlancellot Date: Tue, 12 Dec 2023 10:36:09 -0300 Subject: [PATCH 01/94] feat: add onest-font in application - add onest font in all {content] --- pages/_app.tsx | 10 +++++++++- public/fonts/Onest-VariableFont_wght.woff2 | Bin 0 -> 57500 bytes tailwind.config.ts | 8 ++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 public/fonts/Onest-VariableFont_wght.woff2 diff --git a/pages/_app.tsx b/pages/_app.tsx index 9c01cee7..771a650d 100644 --- a/pages/_app.tsx +++ b/pages/_app.tsx @@ -19,6 +19,12 @@ import { import { RainbowKitSiweNextAuthProvider } from "@rainbow-me/rainbowkit-siwe-next-auth"; import { SwapContextProvider } from "@/components/01-atoms"; import { Toaster } from "react-hot-toast"; +import localFont from "next/font/local"; + +const onest = localFont({ + src: "../public/fonts/Onest-VariableFont_wght.woff2", + variable: "--font-onest", +}); function MyApp({ Component, pageProps: { session, ...pageProps } }: AppProps) { return ( @@ -46,7 +52,9 @@ function MyApp({ Component, pageProps: { session, ...pageProps } }: AppProps) { chains={chains} > - +
+ +
diff --git a/public/fonts/Onest-VariableFont_wght.woff2 b/public/fonts/Onest-VariableFont_wght.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..277374c41bf2a9f58eabb83790dcbd77d04aa558 GIT binary patch literal 57500 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%0Aw7r=jlnFxXyM_Uj@0 z@7CUVZl_yX0yUi9W@@|EBgwBW4)0^Jcq2huALA}?>0cIjzwY3wazBnJ@NBN`;ya7e zxptWUh3CBP((qAgeNT2x>If;n4r*9*Ruz&3)W-!$#yk)T6?iw)x=vqNA3i7y`wx2s1Q2a`m9K3Yu8JXgpAEB9=j%l>(`N|t&|;uVa4 zfKc2p{v?XrqLPhx1?n%fYc8t-#sM8r);0R$A&sFY>eYiGW$qty9M}NtV|J;?(P**V zCZ-uzNhy}Hr#ZWXI8dT+ObN+$tMm=0tRIJquXA{mExsUZX^!XZVsGf;RnD{8A-Y{_ z#J?cTE}XlgQ277<&)utd^WB6b=F+7}sKV2ZaiDO+-y zmZDLF9O&(w4ZD63^7CO$;?yv<(J~#Eui;>;H53+G)m5qWXw}%2#F@8wzKs)x>p&7s z;b1HNLa3#VqawS8Pia8fUM6Sv$ME@n!(et#FD)G;|6!RK^rUz&x~upza$eFMCRbQM zfJ$e+d`&a#M``+Cz}z3^{`J4)8ysHmL`0v|A}|5@72jr7#iNN174M4sKDVF`J1E0u zCPFGRU<$1Ds|KXtjK_scYA#KVFC_zByX$+k{_tk15%Xw+pKPZ6H_aTWZ@xkU4-~R(w_2rCfLA;XBOC(D zItRY>>O=YcTWU^a?lyt!;u)s`LmNolSdY{a%a+JOT+TMC{ZUv*B1gl?iWNIQOfYK3h zEcG-%`dv@yUGOG!;lwfs#_UF>9=<|*k~@8p&uf3e*d=pcT|{vyP#Y`~1kTK}?>j~` zQYWUVbNC}&{NVyD!X`GoD!^rVf_J(BM|R{waw?}`%Vh7HrZ#bPEHjk5>_kP?2t|(Qg-x_tTl}>1ZeNSW zaFSr)4q@+$oD1Pvhzy)HQ?>y$o$Nsvwc4vHZZTMtVk%J>zNt0Ss8;KBhZl9|JDWn@*BFM=-HxW+v;eoIXmnR=2cBr zRRx5*8eV3oNSf(VA(SGZIcldB4QD&7rz)zF9ovoTwc0gjZvSYo7WH(z=sDIkS_?<>BZqtC)K`;p%khIYfuVX*Lg>#wzuBjB=gxEe z+DnpUkbx_EYgs4aIBYB@$qnsU=^(%1#9y*+Px+4eyu0R{_$J4OOBddR(ndDwy%{hW z4SC_^ibo94_oKQI&LeZ)>x@HX#?>8T%7Qv6xMP_oD<@@+{b+=~!Dyy{BVPUg?ELT) zFGx1jy#4p(QcNXD@0HH82sS>S{{%fPxF%Kp1F28v%lvBqT|>I{y)h_kp~$ux803|k z^pqt^Lld5Bc>yN)Y#WnwS=JDHlOzHwD-m+exCxUjIhm`g{H-oQjztz*68UzRrjCu5V~m*% zSi4rcVs(O8a_h73l@imSB2xq^Y>>Vg+zIM~6;&k0mCUinPGTM}hs4^w?twlWw|B(X zWu1gX@?eOdGhaa2|Hg z{MxwOpSS+pQJw^y@hi4!C7biL0^PCvg7>#Rd+niE@dx}1Ps*^AwM5r9)R>;=n=o@Vp zuCGXlOl<{j!9_6YzSfH%U-mGFc>STRn_vXpvKepT(rK4CiMi3)-m2CxLNZ}8mxnlF zGw78J@&`O;0Sjj1T6d_kN(t_&n73t7Wzto7A6}%f{*^o)jd=L-uJCyf&7D3VIs8eYULd9Hp`=%oq zP;_G}Dxt>~r_C)&*M2u9zm4~_UXGJUCKU4zu1b&9fqK<1V8n`wg-R4L72Y~M_4vn} zY~*!99>m62F9yXEkUz6jH8)B&^Z^jw003_u9`~!f_~Ic-_zhk@qP3Oo0UO5VFY|WY zAA|T~0}2h>`VX!1nqDzD%s?guA#zQxpsgP>kp&DGkIu(oZQDapYKTlHZpn5?&ChA3 zBYmC9Gy=#sRZS}Aw07q83Y->qvEAn!P~XnP+r9Ck)p(#Nt8)g)Y<^UMH4kJPD}yP8Mf>l~(Y191 zwEEQStvJv_NFnvphm*A4VtOpY{3+mpgN`4sL^c@c3QK4Y?CHqGCm%}SAeus@y9zzj z_g}9q&GdFKD@s6Nq+5q#ZDEuWxm;hS$vg!eh~gCeu4wNvif;Lb!Y&{R^dLm+JwQ-=&M@6j7Y_<_gee|S zQ{W_hx9~HLiOOG0%iWXf{!d*9Oi3BM0yhd;hbs~BpirC`k z`6lKjbjCHQdu34+Nss4oYC`A@y?+eD8L+0jqoShe)LnO1UgfB8r%RQeVi~L$S5Oal z`Vdx`Bnf3RVE{awf9jXuJEqB%5Yah6*!PDx;;Q_$v?zzwTeaE|=0B@+o}|^eh5!D| zOoR=Mm;?%-(Dxb;CVVtnLi8W(NEeKwKc8d&uqavuovgK25>W_+(D`Er|4RY?k&8zE z%^y$I9|eO8wT}27TG`{lFbA5a?tJeDPKq&4-7VkWn^neQ;_l$V z1JFtO?a@x=2bc%+qM=6-gbS^`*hfTBB!Q<27H4{MP}J1P%xoIQ97+9U={jU4q7kL- zx(fknVV9PJZCXkNnyWIW&1&5Lm8fGLfSWm27L=n@X>p55MaVWjF7iX}MMR?t%CHh)uA& zG!R!5l0cRJDYoUO>|tM$$pr(UUu4Y6)_0U*%8yWYk~Z#6;aV$YCikm?-&tY3;BV=o zp{lY%5lGogFQtMB;hPAaD{0~qpKQLc3-NcF^ZnmNu&X|A&-!$v$Ow;xD{INiLEswIO3u&K zeG=r5^SB-0(ywR$H55`jL~i5MNT#ahc~W^-P^N&C z$;%`lsVFh?Fkho^a6$>)$)<^|hD-keQd%sd5pC}U)`roA4`3OrH178$ngRi%>NQyihHbUtW;VngJx!K1}%zx447x`u}OMRS?GQ zF5M{j7PV>0P%>dNTq8XJUnez{0s{W?vbb~A6gTFGY1RxpyhaS4p!7OyoR{=d-)*2B zUxz;Q2-3#?7uN-gVcd@BioC1(-L@Gj6H9@oSrMR{h{cs+iOXQo7;=gL%S`0B;T$RY zogi~&&iS4f75&u8Cya8*G%SZclG!eNGu1?s?$pPc*E60QTU&>yaI_?O1C_#v5Rmjy zGN-z4=+&l!Wu>TT_X}aHpk$skDm;qHgi9(dSEOI? zNRj3WWzG}jD!;4|BzaT?^ejjEDVx`eoqA_>wm+)Ls>FhDfs6ltfyU5|J-lp+;s8LE zp)yKg!3eb8SX%nXAn@~@?a)^!1H<5&VBoF#nS-qw*TfcCuv)q1BU*uoyn>9I&avh2 zrEd<}4e|B86L?;40T>9sats6iToqs!>{IfIw15{yr=viE1x>9MII|JEx!N{;AW`r-}qNw`R;@=NE6rE}q@vH*XkjOA&5v8>vO%xb}p`SPJ zqPY%PuU<7Kg)FNE_k_Sq?Bk<_kFdfJ22@ZjSdcOlmSk8*w2!rb0M`WTjuWNyoj`Nw zC(4W(r6rPyE;=WkYlF60nw`GwblbrEn7PxmnFwaWEW-u~hdg!DPU?l+&=pllSBVVQ z1}pGxm0;M!%qNkK_)^PLwupe=C;4F`mR&$E0<#~CY7&lv3r)axOMatmgK?;B_(SQQ zGsQIm*W+?EqfBMv5xW4!Xk~Q`cyX0>EC=F&;mT&5%1~&457%!iL@dI_igo%x22?rc z<#Tfu)YW45)^@$J-qfpNn6rpWUolCB#702U$(Y_9EuUrQwj6FW1(lo&>EoW{wKUqG zsA!YKnx&v|g$55<@=9X02+Bx8S6yKRB78(tlnIDLU$hoK6FP~ACCw${%H|^!$Uvt8 zExEAHHCbI?7;pv2SZBWMK6#{Td9}KY9p^y?h`PNx7KUY`YS$`Z7hKm=OXV9gk>*6@ zT8goqfuOe*%|WT(YRLeknWXvy0@X%x4PU(_y_q)``-vEh)pu)6(GNtf+(=Xa?ZhKa1BzQTa-gPwNW(B1hnd%%bBMPl#T!`qHRO9L@ z5mbOOO2?%$c?*$d*vA6m2=Tq<9jU2gXjRMw`tiwom=|*IQ!n`y!RQ%kcBFyq#(c^W zuL3gP0)jWDLJ9=JTOY!g?}yKuM|a=3Z~D!Pih1UTHHP_OjmOMGGwwi;8pd+Dd{>>I z&G9yA3<^eq)8?RrRr$WAPqJdA`)_x!@$9JJ)0j6qvSDr4k1+AvisXxQhI7L>pyA7n z(c9node8HtoNBK=Sfy|3X#8pz1G35<(UBaKzeXoYv07On@y`Ud4h z2vi!^tr_MdlkNCuEK>c@g;duxD%+{nznZwy>_8bkSDBKNh9P&5O4PORScuDj)FgdG zD9u3OBUA;wo0`9snGDRqWsPwT!eaF<&rgNjB7gM~|Ca#-(1_OTfFo~MnLF4pG(|ih* zNfb3Y;-z>go?^tb-CZM2C)Jf;W&YS4P}w*Q5ouIFM24^$(in+t?@|Z>>V>4!NT@aq)%;?Q zAmpi4VU_eV$?t)Rj9Gji`6~+CO*60rsvMri8urzA?ZD746lg)UO3UK4)|^y`7sK77 zEE=3~xD+`^9j&uw(A(1p!GrA(`MR`4%g&B-v|55J{=2e)fn**!rJR^~GR3e?R<;zw zl(FFhK^Ns9Lzw3GhdS3EzN1=UC69ZF)oupeH{aHyU{Uj1ztEsN9QKB1N*1nw8=>M2 zMG!u1Kmpo^u&>!3WN*9sRL12A;h~%tMZ7cTUG29KA!r4-gCUW-K`s%x$yJ7CwrU-z+ zQj^_rxe;l2Jy*p^ZlB0i5@+;Ku+<8wqziAxy+l2t@fIphUgI%O;aj*djFN`vdkB5c zv)J;aLJdWOr$JhHs|3V(u}DD#rdV!Ty5p)ruHWmaw;QJq0&!+`ZfZFRvj)z%ACfGL zTFZzVk7abKw^wzFk_CVQ>j9P@85{zRIWi6G6P;7l29IYpfj*Y_(ozM|+2xbS){kIT zT_4kWe1xRbhPk+o{%gBP1d%EoUGS!?@hy+u(nSRo6_EBwE~Jr6q+it&9#^q5Liz^R zIZ;Mwe$t$6XoYny`A@U+aK-PjBu@CYFEh9m%7jGmNR1Fx9;eA>Y_*1aYqc?_Xc$S8 zWx?Iz6Ww+!Q*e!-dvRJmU`0um$AnEdna$6-8Mel1g=aL>VNN_$wV9JO1*d8l5h9C; zcsNi@HFB0$@wO;CZ zzy(=E=^dZge>$B_C0|exgh0s5!+u-k+KzGT_ZDM+%nR1|T4YlK@pq>!*iMi$;UsK% zJD=`htv^te8E2(41ZVkMU%aCiyPZ=@&ppxihd(>EUe#7CrAbTLgb(G@@*~tKNS@_& zb)kAomQLxnfghsy$s_f={*?5XM;3m^FWqKFJh z;@P~oV7|KY{5enqiZXiFyZ>1|#zFWQKjD}7S}T#GfG2CqX3lpgkWRZzfD%x1!q$C* z=zop_1JD=;?(|;o!C+93y-%L}<@ptp;#`RmlnNza>D5)nlYOL{O%G9C!}$wPiPd5*s_0=f(0(T-dJ!F2FyppUF6$cf_ zBvImGarEl(+m>rs5%3ws21XmbIgcMzk1DaSp^cBoM^wB3^Ez!NTfCv+ycrvCRQrJ~ z^y+i(ZVmf$B6zo8jl5>kEZEG$;%T~TdvV?~v&{shBuftSq>&9P7_sBz@FbCzicR+; z#Ng@X@c7&|114+A6s`fQ99oeRDAg;h9I=K=} zFDB4Y+)+$Qs?84q9qqn-f5yy9;?zh2!nH)`p{(C?`LdNryhl<@L$uW?OkV%I|C{j zcGI*w{2q6ZmOh_pmfTz?hbkR7`nwPQgLLDQ*~f!yv)#VP7CYuB1>jV3?Cst}JP{0U zocgN&%YgU3l&)jB)mN_D2K(JqBp8AccKM&*Jw1Ew-S^%(af-mjC(o&N-lhgaRdsD$d1)oZ z1oHkG7MIElp*)HG#nOBq0c)Y1I!v=?b~zdwk=1ZKK;Ad-s~`y{dvBB-`+nTsD1NEe3yQG zdbPOORI4b5L|-_}N^1oo`gn;%Ys$FRJC^XS4$hdqxUWloBiM5J(bdZ88s+SS2!@^a zpZ>qQKmf1+i-Rg&S10tliokOft0I&F_Ltz1u0zQIfzly}^XD#b-@fx#SLKojVr(~V zBxA=F?C)eBCcCRk;xcEpfD?fcAf+9N0cauQsg+pbf6?1}Md%%k0~K)esz5!pbu0yY zI@cRJGcJw`unSurE|FScSaH^+eLlK?k)l@#&Ff-SF}=!&_>^%ODs$_AOup7I@`ZHivNI3~A^CZOV%40-rB6xaAaV(8#K=hUX&D- zp*Uo_t0ybW(^1=$u_vyW%y`zA3W<4g2t)b|caHFA28MAC&+!aba0mx*1m|%xao*1& z$RGI9&av^aEY%yWl~mJ(f1}E}d~}dbqMH7cGs0-WW4F|Qiq3Gmj_j{PCdGGj-B$6e zuc1K=VTG?1xCGBC_C-P8U|DWG?giz#PpC<2x2!Sgnu~G^%GfCWI z3TY4s-4}T)nD7X)Y@)nJEad~C%`o4|Wb?Tc?D1Sn5x=8_vShe-D}~!GeVp0zK41pG z`^z6gECQ*bs=D9FKis8i7p@h+n_zO5Mb5(lW6pM@`wpg&7jT)FW?EecHzo#W4{+AX zRl>=n9SvWO0nWot+KX^HENFUB70yD*jWmH)55YBf4R1`jOcE;_7KE`00%PmZD&ABW zNgyg=k7XE|!lP@)WJ@iV%KD%br}*`bvv2rp8Ja5Wxr?j=IFzVi-X!jYBycpU>`RLm zRM6u{2!aIdQij(0eoks$#!XBZ;Fe&Fs#;2JF1D*?Vp0`!z24>x6OE{fA}6ieW-{fB z#Th**|+xyEyVZ(EE-rw@<>fA{x!zOjJ=?hsp0x`{smEnb|;kZ0ZSE6Qc&3IlTUpk2}SAla~ zu&eni2v$@du+7Ql!KxqqVjU$w4N?(wk|_@nd2aWST_32(XeItr&IKXLt(=7 z&+v$2bAg0m(eNcbqpgCdrt0TZ-qv}8W_z_Q@M5-raZq=4u=>_IQO~P!_3ckxTFN=K zK1w}31J5c(alRFF`(V3=CuBlMqmoG3(!qaaxg7DNX{1buA_5-)$FcSs%l)7O z5}bsSCXFngMs|wGyQ-6Rhb18*i<#8vj?ANC6jm}Wj-5cNY#xBYwZJpB6fk@V+9KzT zr4whadKKYX*RrcsQ6cl|F>W1m2-pJ_RLj_kBFl3gOOl3j5!-QSa9!iT%*bX0ZY8Cg zJrx9TIwe#|vJ8GqW~ykZB_Y+hRf_^VuEQ?L0jDUI1he_r&^4>vLgy87;McnbC>nWI zjmXBG#u?NhPuEpuEVM#*s=eM%TlP5r%=pcSB~w(`!7|adW;;r|h7+54=qemm61J~1 zSc%09u9Snbpjyyi!*OQja7#RhX=sU&9~Tm|3n6f2ebdlf4ECla;USvqXNSA8Z6pYxns*_Pxz*%hWHY!Z`;5HqEwJ{90#H}*4s%PC2}br$;ikf zkL5Ln#5>F`k&a$wafGcQJ2kvLp&JMZz;r7>3#pgaJkmzU9cvri7WBIz7^sz__Be(4 zj4*VxGNvIm-_jAsMA7Z@GItXM5sGuu5Qw#*nY57uP&)D^8K?t=haQUPP3D{w^kp6z zCuNFKAPO&kN?9k$*w-lH+t$kaKk{2Zqe^2TN9 zT6tQL=i`=E1z;LX-?}z+P=n&3AAvgW7RE0 zHj57|jTp0e9a-{*PStN1wKIZk7SWA3Nas!dTiX1CM1R4nx@l zX0j*HKLTU#uPj|eu+Ex1eromMgGX!gFi$>YDE{HCR_hl|FZT4`hl29POhh{Ecb8m1 zLCu0F2S>-K>j4u95|(FiD{}T#GI&xBeb-LqEJmP#>&HR>VLEgNG3Q64EHk--93EaN zp{1;hhC~uMQmNkbs=YTQnd^4E_uiwOiw=w~Holt6X`_or^?O}^@1p6=Pt>qdpHZO_ znv;kP=}&?|Hao7WUOKLHay%JoW|6{@m_#IOPquwz%T$Hj`=JERzb@0HC>xOfdxvG2 zBhY~D79nP5y!=uCC+man?hemFC!k$gwAxE3E(;7S zksS!CpH6rxsLei?x?>vrjoyVHjDH)c)hXTYb{b@%Q}x<3gDr-{`ZCvYozN04-2J3S zl)csn0*|<*36gaXscFVF&|5~Ad&0IR-AW2v^!!c=6PQrUS|)pjVTB?C^&+L26u_=? z6aG_8*LdW56LG8S&ES`8(CfE7h&PXSY|wnD)k#wzKo8GK)*8SGiz4dQtJTk4E%#X? z+Qmj;8+urS#Q;fI3u{feA}JD)w`4m=tEEOnv_PG$?%0Do8F}0wHP!M@(8W%c5}{~L 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 KAIInc0000%F`JYC literal 0 HcmV?d00001 diff --git a/tailwind.config.ts b/tailwind.config.ts index ce518de3..76e2f22b 100644 --- a/tailwind.config.ts +++ b/tailwind.config.ts @@ -5,6 +5,14 @@ const config: Config = { "./pages/**/*.{js,ts,jsx,tsx,mdx}", "./components/**/*.{js,ts,jsx,tsx,mdx}", ], + theme: { + extend: { + fontFamily: { + onest: ["var(--font-onest)"], + }, + }, + }, + plugins: [], }; export default config; From c61f1909e8c76c3bdb098136f18cfb6e192dfa8d Mon Sep 17 00:00:00 2001 From: heronlancellot Date: Mon, 18 Dec 2023 11:52:24 -0300 Subject: [PATCH 02/94] feat: add fonts & dark/light mode - add onest font - add dark/light mode - change text-fonts and color switching light/dark - add new layout like figma --- components/01-atoms/ConnectWallet.tsx | 4 +- components/01-atoms/SearchBar.tsx | 31 +++++++++---- components/01-atoms/SelectAuthedUserChain.tsx | 2 +- components/01-atoms/SelectDestinyChain.tsx | 2 +- components/01-atoms/Tab.tsx | 8 ++-- components/01-atoms/icons/PersonIcon.tsx | 22 ++++++++++ components/01-atoms/icons/SelectUserIcon.tsx | 23 ++++++++++ components/01-atoms/icons/SwaplaceIcon.tsx | 6 +-- components/01-atoms/icons/WalletIcon.tsx | 22 ++++++++++ components/02-molecules/CardHome.tsx | 8 ++-- components/02-molecules/NftCard.tsx | 2 +- components/02-molecules/OfferSummary.tsx | 11 +++-- components/02-molecules/SwapStation.tsx | 14 +++--- components/02-molecules/TheHeader.tsx | 41 +++++++++++++++--- components/03-organisms/NftsShelf.tsx | 29 +++++++++---- components/03-organisms/SwappingShelfs.tsx | 2 +- components/04-templates/SwapSection.tsx | 4 +- package-lock.json | 11 +++++ package.json | 1 + pages/_app.tsx | 10 +++-- pages/_document.tsx | 2 +- styles/global.css | 43 ++++++++++++++++++- tailwind.config.ts | 1 + 23 files changed, 243 insertions(+), 56 deletions(-) create mode 100644 components/01-atoms/icons/PersonIcon.tsx create mode 100644 components/01-atoms/icons/SelectUserIcon.tsx create mode 100644 components/01-atoms/icons/WalletIcon.tsx diff --git a/components/01-atoms/ConnectWallet.tsx b/components/01-atoms/ConnectWallet.tsx index 4be484ff..f53d0c54 100644 --- a/components/01-atoms/ConnectWallet.tsx +++ b/components/01-atoms/ConnectWallet.tsx @@ -65,7 +65,7 @@ export const ConnectWallet = ({ customStyle }: IConnectWallet) => {
-
+
-

Your network:

+

Your network:

-

Searched address network:

+

+ Searched address network: +

diff --git a/components/01-atoms/SelectAuthedUserChain.tsx b/components/01-atoms/SelectAuthedUserChain.tsx index 8a8a9250..fc36125b 100644 --- a/components/01-atoms/SelectAuthedUserChain.tsx +++ b/components/01-atoms/SelectAuthedUserChain.tsx @@ -49,7 +49,7 @@ export const SelectAuthedUserChain = () => {
+ ) : ( + + )} +
+
+ +
+
); }; diff --git a/components/03-organisms/NftsShelf.tsx b/components/03-organisms/NftsShelf.tsx index 5ecfbcac..904e498f 100644 --- a/components/03-organisms/NftsShelf.tsx +++ b/components/03-organisms/NftsShelf.tsx @@ -11,6 +11,8 @@ import { getNftsFrom } from "@/lib/client/blockchain-data"; import { SwapContext, SwapIcon } from "../01-atoms"; import { EthereumAddress } from "@/lib/shared/types"; import { useNetwork } from "wagmi"; +import { SelectUserIcon } from "../01-atoms/icons/SelectUserIcon"; +import { useTheme } from "next-themes"; /** * @@ -29,6 +31,7 @@ export const NftsShelf = ({ address }: INftsShelfProps) => { const [nftsQueryStatus, setNftsQueryStatus] = useState( NFTsQueryStatus.EMPTY_QUERY ); + const { theme } = useTheme(); const { authenticatedUserAddress } = useAuthenticatedUser(); const { validatedAddressToSwap, inputAddress, destinyChain } = @@ -86,7 +89,7 @@ export const NftsShelf = ({ address }: INftsShelfProps) => { }, [validatedAddressToSwap]); return ( -
+
{nftsQueryStatus == NFTsQueryStatus.WITH_RESULTS && nftsList ? ( @@ -94,26 +97,34 @@ export const NftsShelf = ({ address }: INftsShelfProps) => {
) : nftsQueryStatus == NFTsQueryStatus.EMPTY_QUERY || !address ? ( -
+
- -

- Select a user to start swapping +

+ +
+

+ No user selected yet +

+

+ Search for a user to start swapping items

) : nftsQueryStatus == NFTsQueryStatus.NO_RESULTS ? ( -
+
-

+

Given address has no NFTs associated in the given network

) : nftsQueryStatus == NFTsQueryStatus.LOADING ? ( -
+
-

+

Loading NFTs of{" "} {new EthereumAddress(address).getEllipsedAddress()}...

diff --git a/components/03-organisms/SwappingShelfs.tsx b/components/03-organisms/SwappingShelfs.tsx index bfbcc9c5..59e5ee63 100644 --- a/components/03-organisms/SwappingShelfs.tsx +++ b/components/03-organisms/SwappingShelfs.tsx @@ -25,7 +25,7 @@ export const SwappingShelfs = () => { }, [chain]); return ( -
+
setActiveSwappingShelfID(input)} /> diff --git a/components/04-templates/SwapSection.tsx b/components/04-templates/SwapSection.tsx index 33651c15..86da397f 100644 --- a/components/04-templates/SwapSection.tsx +++ b/components/04-templates/SwapSection.tsx @@ -4,8 +4,8 @@ import { SwapStation } from "@/components/02-molecules"; export const SwapSection = () => { return ( -
-
+
+
diff --git a/package-lock.json b/package-lock.json index 356115bf..892b6322 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,6 +16,7 @@ "ethers": "^5.7.2", "next": "14.0.3", "next-auth": "^4.20.1", + "next-themes": "^0.2.1", "react": "^18", "react-dom": "^18", "react-hot-toast": "^2.4.1", @@ -6633,6 +6634,16 @@ } } }, + "node_modules/next-themes": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/next-themes/-/next-themes-0.2.1.tgz", + "integrity": "sha512-B+AKNfYNIzh0vqQQKqQItTS8evEouKD7H5Hj3kmuPERwddR2TxvDSFZuTj6T7Jfn1oyeUyJMydPl1Bkxkh0W7A==", + "peerDependencies": { + "next": "*", + "react": "*", + "react-dom": "*" + } + }, "node_modules/next/node_modules/postcss": { "version": "8.4.31", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", diff --git a/package.json b/package.json index 5af5469c..ffe53967 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "ethers": "^5.7.2", "next": "14.0.3", "next-auth": "^4.20.1", + "next-themes": "^0.2.1", "react": "^18", "react-dom": "^18", "react-hot-toast": "^2.4.1", diff --git a/pages/_app.tsx b/pages/_app.tsx index 771a650d..3a4a3b0e 100644 --- a/pages/_app.tsx +++ b/pages/_app.tsx @@ -20,6 +20,8 @@ import { RainbowKitSiweNextAuthProvider } from "@rainbow-me/rainbowkit-siwe-next import { SwapContextProvider } from "@/components/01-atoms"; import { Toaster } from "react-hot-toast"; import localFont from "next/font/local"; +import cc from "classcat"; +import { ThemeProvider } from "next-themes"; const onest = localFont({ src: "../public/fonts/Onest-VariableFont_wght.woff2", @@ -52,9 +54,11 @@ function MyApp({ Component, pageProps: { session, ...pageProps } }: AppProps) { chains={chains} > -
- -
+ +
+ +
+
diff --git a/pages/_document.tsx b/pages/_document.tsx index cec067eb..1ccd8e8e 100644 --- a/pages/_document.tsx +++ b/pages/_document.tsx @@ -4,7 +4,7 @@ export default function Document() { return ( - +
diff --git a/styles/global.css b/styles/global.css index 69c92b45..fdd36631 100644 --- a/styles/global.css +++ b/styles/global.css @@ -1,11 +1,52 @@ html, body { - width: 100vw; overflow-x: hidden; } + input[type="search"]::-webkit-search-decoration, input[type="search"]::-webkit-search-cancel-button, input[type="search"]::-webkit-search-results-button, input[type="search"]::-webkit-search-results-decoration { display: none; } + +@tailwind base; +@tailwind components; +@tailwind utilities; + +@layer utilities { + .title-h1 { + } + + .title-h2 { + } + + .title-h3-normal { + @apply font-onest font-normal text-[20px] leading-[25.5px] text-[#333333]; + } + + .title-h3-normal-dark { + @apply font-onest font-normal text-[20px] leading-[25.5px] text-[#F6F6F6]; + } + + .p-medium-bold { + @apply font-onest font-medium text-[14px] leading-[16px] text-[#707572]; + } + .p-medium-bold-dark { + @apply font-onest font-medium text-[14px] leading-[16px] text-[#F6F6F6]; + } + + .p-medium { + @apply font-onest font-medium text-[14px] leading-[20px] text-[#707572]; + } + .p-medium-dark { + @apply font-onest font-medium text-[14px] leading-[20px] text-[#F6F6F6]; + } + + .p-small { + @apply font-onest font-normal text-[14px] leading-[20px] text-[#707572]; + } + .p-small-dark { + @apply font-onest font-normal text-[14px] leading-[20px] text-[#F6F6F6]; + } +} diff --git a/tailwind.config.ts b/tailwind.config.ts index 76e2f22b..623c4e09 100644 --- a/tailwind.config.ts +++ b/tailwind.config.ts @@ -1,6 +1,7 @@ import type { Config } from "tailwindcss"; const config: Config = { + darkMode: ["class"], content: [ "./pages/**/*.{js,ts,jsx,tsx,mdx}", "./components/**/*.{js,ts,jsx,tsx,mdx}", From cb6b3281901186ef248501284d900a7d15430014 Mon Sep 17 00:00:00 2001 From: heronlancellot Date: Mon, 18 Dec 2023 12:46:29 -0300 Subject: [PATCH 03/94] refactor: adjust imports - refactor all imports & remove unused --- components/01-atoms/ConfirmSwapModal.tsx | 10 +++------- components/01-atoms/LoadingIndicator.tsx | 4 +--- components/01-atoms/SearchBar.tsx | 4 ++-- components/01-atoms/SelectDestinyChain.tsx | 5 +++-- components/01-atoms/TransactionResultModal.tsx | 7 +++---- components/01-atoms/icons/index.tsx | 10 ++++++++++ components/01-atoms/index.ts | 8 +------- components/02-molecules/CardHome.tsx | 3 ++- components/02-molecules/NftCard.tsx | 2 +- components/02-molecules/NftsList.tsx | 2 +- components/02-molecules/OfferSummary.tsx | 7 ++++--- components/02-molecules/SwapStation.tsx | 7 ++----- components/02-molecules/TheHeader.tsx | 4 ++-- components/02-molecules/index.tsx | 6 +++--- components/03-organisms/NftsShelf.tsx | 17 ++++++----------- components/03-organisms/SwappingShelfs.tsx | 2 +- components/03-organisms/index.tsx | 1 + components/04-templates/SwapSection.tsx | 2 +- components/04-templates/index.tsx | 2 +- 19 files changed, 48 insertions(+), 55 deletions(-) create mode 100644 components/01-atoms/icons/index.tsx diff --git a/components/01-atoms/ConfirmSwapModal.tsx b/components/01-atoms/ConfirmSwapModal.tsx index f137efdb..a2f98317 100644 --- a/components/01-atoms/ConfirmSwapModal.tsx +++ b/components/01-atoms/ConfirmSwapModal.tsx @@ -1,12 +1,5 @@ import { Dialog, Transition } from "@headlessui/react"; import { Fragment, useContext, useEffect, useState } from "react"; -import { - NftCard, - NftCardActionType, - SwapContext, - SwapIcon, - TransactionResultModal, -} from "."; import { useAuthenticatedUser } from "@/lib/client/hooks/useAuthenticatedUser"; import { makeSwap } from "@/lib/client/blockchain-data"; import { SWAPLACE_SMART_CONTRACT_ADDRESS } from "@/lib/client/constants"; @@ -14,6 +7,9 @@ import { useNetwork, useWalletClient } from "wagmi"; import { getTimestamp } from "@/lib/client/utils"; import { signTransaction } from "viem/actions"; import toast from "react-hot-toast"; +import { SwapContext, TransactionResultModal } from "@/components/01-atoms"; +import { NftCard, NftCardActionType } from "@/components/02-molecules"; +import { SwapIcon } from "@/components/01-atoms/icons"; interface ConfirmSwapModalProps { open: boolean; diff --git a/components/01-atoms/LoadingIndicator.tsx b/components/01-atoms/LoadingIndicator.tsx index 1107a5db..d432d0ae 100644 --- a/components/01-atoms/LoadingIndicator.tsx +++ b/components/01-atoms/LoadingIndicator.tsx @@ -1,7 +1,5 @@ import React from "react"; -const LoadingIndicator = () => ( +export const LoadingIndicator = () => (
); - -export default LoadingIndicator; diff --git a/components/01-atoms/SearchBar.tsx b/components/01-atoms/SearchBar.tsx index 72ae246f..d09f8835 100644 --- a/components/01-atoms/SearchBar.tsx +++ b/components/01-atoms/SearchBar.tsx @@ -1,11 +1,11 @@ import cc from "classcat"; import { useContext, useEffect, useState } from "react"; +import { MagnifyingGlassIcon } from "@/components/01-atoms/icons"; import { - MagnifyingGlassIcon, SelectAuthedUserChain, SelectDestinyChain, SwapContext, -} from "."; +} from "@/components/01-atoms"; import { useAuthenticatedUser } from "@/lib/client/hooks/useAuthenticatedUser"; import { ENS } from "web3-eth-ens"; import Web3 from "web3"; diff --git a/components/01-atoms/SelectDestinyChain.tsx b/components/01-atoms/SelectDestinyChain.tsx index 3372b70a..1e84ea76 100644 --- a/components/01-atoms/SelectDestinyChain.tsx +++ b/components/01-atoms/SelectDestinyChain.tsx @@ -1,6 +1,7 @@ -import { Dialog, Transition } from "@headlessui/react"; import { Fragment, useContext, useState } from "react"; -import { EthereumIcon, PolygonIcon, SwapContext } from "."; +import { Dialog, Transition } from "@headlessui/react"; +import { SwapContext } from "@/components/01-atoms"; +import { EthereumIcon, PolygonIcon } from "@/components/01-atoms/icons"; import { ChainInfo, SupportedNetworks } from "@/lib/client/constants"; import cc from "classcat"; diff --git a/components/01-atoms/TransactionResultModal.tsx b/components/01-atoms/TransactionResultModal.tsx index 464c8866..5dcb5385 100644 --- a/components/01-atoms/TransactionResultModal.tsx +++ b/components/01-atoms/TransactionResultModal.tsx @@ -1,9 +1,8 @@ -import { Dialog, Transition } from "@headlessui/react"; -import { TransactionResult } from "."; import { Fragment, useState } from "react"; -import LoadingIndicator from "./LoadingIndicator"; +import { Dialog, Transition } from "@headlessui/react"; +import { TransactionResult, LoadingIndicator } from "@/components/01-atoms"; +import { DangerIcon } from "@/components/01-atoms/icons"; import { CheckmarkIcon } from "react-hot-toast"; -import { DangerIcon } from "./icons/DangerIcon"; interface TransactionResultModalProps { onClose: () => void; diff --git a/components/01-atoms/icons/index.tsx b/components/01-atoms/icons/index.tsx new file mode 100644 index 00000000..7a2f2796 --- /dev/null +++ b/components/01-atoms/icons/index.tsx @@ -0,0 +1,10 @@ +export * from "./DangerIcon"; +export * from "./EthereumIcon"; +export * from "./MagnifyingGlassIcon"; +export * from "./PaperPlane"; +export * from "./PersonIcon"; +export * from "./PolygonIcon"; +export * from "./SelectUserIcon"; +export * from "./SwapIcon"; +export * from "./SwaplaceIcon"; +export * from "./WalletIcon"; diff --git a/components/01-atoms/index.ts b/components/01-atoms/index.ts index 988081da..0355c2c5 100644 --- a/components/01-atoms/index.ts +++ b/components/01-atoms/index.ts @@ -1,15 +1,9 @@ export * from "./ConnectWallet"; -export * from "../02-molecules/NftCard"; export * from "./SearchBar"; export * from "./SelectAuthedUserChain"; export * from "./Tab"; export * from "./SwapContext"; -export * from "./icons/SwaplaceIcon"; -export * from "./icons/MagnifyingGlassIcon"; -export * from "./icons/SwapIcon"; -export * from "./icons/PaperPlane"; export * from "./SelectDestinyChain"; -export * from "./icons/EthereumIcon"; -export * from "./icons/PolygonIcon"; export * from "./ConfirmSwapModal"; export * from "./TransactionResultModal"; +export * from "./LoadingIndicator"; diff --git a/components/02-molecules/CardHome.tsx b/components/02-molecules/CardHome.tsx index d11bc641..ff440e52 100644 --- a/components/02-molecules/CardHome.tsx +++ b/components/02-molecules/CardHome.tsx @@ -1,5 +1,6 @@ import React from "react"; -import { ConnectWallet, SwaplaceIcon } from "@/components/01-atoms"; +import { ConnectWallet } from "@/components/01-atoms"; +import { SwaplaceIcon } from "@/components/01-atoms/icons"; export const CardHome = () => { return ( diff --git a/components/02-molecules/NftCard.tsx b/components/02-molecules/NftCard.tsx index df66d13b..614282f0 100644 --- a/components/02-molecules/NftCard.tsx +++ b/components/02-molecules/NftCard.tsx @@ -1,6 +1,6 @@ import { NFT } from "@/lib/client/constants"; import React, { useContext, useEffect, useState } from "react"; -import { SwapContext } from "../01-atoms"; +import { SwapContext } from "@/components/01-atoms"; import { useAuthenticatedUser } from "@/lib/client/hooks/useAuthenticatedUser"; import { EthereumAddress } from "@/lib/shared/types"; import cc from "classcat"; diff --git a/components/02-molecules/NftsList.tsx b/components/02-molecules/NftsList.tsx index 06fe1db1..f56fc33f 100644 --- a/components/02-molecules/NftsList.tsx +++ b/components/02-molecules/NftsList.tsx @@ -1,5 +1,5 @@ import { NFT } from "@/lib/client/constants"; -import { NftCard } from "../01-atoms"; +import { NftCard } from "@/components/02-molecules"; interface INftsList { nftsList: NFT[]; diff --git a/components/02-molecules/OfferSummary.tsx b/components/02-molecules/OfferSummary.tsx index 5fe72c25..633b7d57 100644 --- a/components/02-molecules/OfferSummary.tsx +++ b/components/02-molecules/OfferSummary.tsx @@ -1,10 +1,11 @@ import { useContext } from "react"; -import { EthereumIcon, NftCard, PolygonIcon, SwapContext } from "../01-atoms"; import { useEnsName, useNetwork } from "wagmi"; import { EthereumAddress } from "@/lib/shared/types"; import { useAuthenticatedUser } from "@/lib/client/hooks/useAuthenticatedUser"; -import { ChainInfo, SupportedNetworks } from "@/lib/client/constants"; -import { PersonIcon } from "../01-atoms/icons/PersonIcon"; +import { ChainInfo } from "@/lib/client/constants"; +import { SwapContext } from "@/components/01-atoms"; +import { PersonIcon } from "@/components/01-atoms/icons"; +import { NftCard } from "@/components/02-molecules"; interface IOfferSummary { forAuthedUser: boolean; diff --git a/components/02-molecules/SwapStation.tsx b/components/02-molecules/SwapStation.tsx index 889537ce..1831bf6b 100644 --- a/components/02-molecules/SwapStation.tsx +++ b/components/02-molecules/SwapStation.tsx @@ -1,10 +1,7 @@ import { useContext, useEffect, useState } from "react"; +import { ConfirmSwapModal, SwapContext } from "@/components/01-atoms"; +import { PaperPlane } from "@/components/01-atoms/icons"; import { OfferSummary } from "@/components/02-molecules"; -import { - ConfirmSwapModal, - PaperPlane, - SwapContext, -} from "@/components/01-atoms"; import cc from "classcat"; import toast from "react-hot-toast"; diff --git a/components/02-molecules/TheHeader.tsx b/components/02-molecules/TheHeader.tsx index 4b61a8d0..17714bca 100644 --- a/components/02-molecules/TheHeader.tsx +++ b/components/02-molecules/TheHeader.tsx @@ -1,10 +1,10 @@ import React, { useEffect, useState } from "react"; -import { ConnectWallet, SwaplaceIcon } from "@/components/01-atoms"; import cc from "classcat"; import { useScreenSize } from "@/lib/client/hooks/useScreenSize"; import { useAuthenticatedUser } from "@/lib/client/hooks/useAuthenticatedUser"; import { useTheme } from "next-themes"; -import { WalletIcon } from "../01-atoms/icons/WalletIcon"; +import { ConnectWallet } from "@/components/01-atoms"; +import { SwaplaceIcon, WalletIcon } from "@/components/01-atoms/icons/"; export const TheHeader = () => { const { isDesktop } = useScreenSize(); diff --git a/components/02-molecules/index.tsx b/components/02-molecules/index.tsx index 9ff6d1dd..d2a6e13e 100644 --- a/components/02-molecules/index.tsx +++ b/components/02-molecules/index.tsx @@ -1,6 +1,6 @@ export * from "./CardHome"; -export * from "./TheHeader"; -export * from "../03-organisms/NftsShelf"; +export * from "./NftCard"; export * from "./NftsList"; -export * from "./SwapStation"; export * from "./OfferSummary"; +export * from "./SwapStation"; +export * from "./TheHeader"; diff --git a/components/03-organisms/NftsShelf.tsx b/components/03-organisms/NftsShelf.tsx index 904e498f..fcbda686 100644 --- a/components/03-organisms/NftsShelf.tsx +++ b/components/03-organisms/NftsShelf.tsx @@ -1,18 +1,13 @@ import { useContext, useEffect, useState } from "react"; -import { - NFT, - ChainInfo, - NFTsQueryStatus, - ADDRESS_ZERO, -} from "@/lib/client/constants"; +import { NFT, ChainInfo, NFTsQueryStatus } from "@/lib/client/constants"; import { useAuthenticatedUser } from "@/lib/client/hooks/useAuthenticatedUser"; -import { NftsList } from "../02-molecules"; -import { getNftsFrom } from "@/lib/client/blockchain-data"; -import { SwapContext, SwapIcon } from "../01-atoms"; -import { EthereumAddress } from "@/lib/shared/types"; import { useNetwork } from "wagmi"; -import { SelectUserIcon } from "../01-atoms/icons/SelectUserIcon"; +import { getNftsFrom } from "@/lib/client/blockchain-data"; import { useTheme } from "next-themes"; +import { EthereumAddress } from "@/lib/shared/types"; +import { SwapContext } from "@/components/01-atoms"; +import { SelectUserIcon } from "@/components/01-atoms/icons"; +import { NftsList } from "@/components/02-molecules"; /** * diff --git a/components/03-organisms/SwappingShelfs.tsx b/components/03-organisms/SwappingShelfs.tsx index 59e5ee63..7732ff33 100644 --- a/components/03-organisms/SwappingShelfs.tsx +++ b/components/03-organisms/SwappingShelfs.tsx @@ -1,7 +1,7 @@ import cc from "classcat"; import { useContext, useEffect, useState } from "react"; -import { NftsShelf } from "@/components/02-molecules"; import { SwapContext, SwappingShelfID, Tab } from "@/components/01-atoms/"; +import { NftsShelf } from "@/components/03-organisms"; import { useAuthenticatedUser } from "@/lib/client/hooks/useAuthenticatedUser"; import { useNetwork } from "wagmi"; diff --git a/components/03-organisms/index.tsx b/components/03-organisms/index.tsx index fa5458de..6ce0cddd 100644 --- a/components/03-organisms/index.tsx +++ b/components/03-organisms/index.tsx @@ -1 +1,2 @@ +export * from "./NftsShelf"; export * from "./SwappingShelfs"; diff --git a/components/04-templates/SwapSection.tsx b/components/04-templates/SwapSection.tsx index 86da397f..476eef40 100644 --- a/components/04-templates/SwapSection.tsx +++ b/components/04-templates/SwapSection.tsx @@ -1,6 +1,6 @@ import { SearchBar } from "@/components/01-atoms"; -import { SwappingShelfs } from "@/components/03-organisms"; import { SwapStation } from "@/components/02-molecules"; +import { SwappingShelfs } from "@/components/03-organisms"; export const SwapSection = () => { return ( diff --git a/components/04-templates/index.tsx b/components/04-templates/index.tsx index cf73a80e..a8ff2ccc 100644 --- a/components/04-templates/index.tsx +++ b/components/04-templates/index.tsx @@ -1,3 +1,3 @@ export * from "./HomeSection"; -export * from "./SwapSection"; export * from "./Layout"; +export * from "./SwapSection"; From f97e6b5936bbf9df0ed38c7a3493bb2a8293d222 Mon Sep 17 00:00:00 2001 From: heronlancellot Date: Mon, 18 Dec 2023 19:16:04 -0300 Subject: [PATCH 04/94] feat: add swaplace header icons - add header & icons changing with theme --- components/01-atoms/SwappingIcons.tsx | 109 ++++++++++++++++++ components/01-atoms/icons/ChatIcon.tsx | 22 ++++ .../01-atoms/icons/NotificationsIcon.tsx | 22 ++++ components/01-atoms/icons/OffersIcon.tsx | 22 ++++ components/01-atoms/icons/SwappingIcon.tsx | 22 ++++ components/01-atoms/icons/index.tsx | 4 + components/01-atoms/index.ts | 5 +- components/02-molecules/CardHome.tsx | 8 +- components/02-molecules/TheHeader.tsx | 26 +++-- 9 files changed, 225 insertions(+), 15 deletions(-) create mode 100644 components/01-atoms/SwappingIcons.tsx create mode 100644 components/01-atoms/icons/ChatIcon.tsx create mode 100644 components/01-atoms/icons/NotificationsIcon.tsx create mode 100644 components/01-atoms/icons/OffersIcon.tsx create mode 100644 components/01-atoms/icons/SwappingIcon.tsx diff --git a/components/01-atoms/SwappingIcons.tsx b/components/01-atoms/SwappingIcons.tsx new file mode 100644 index 00000000..6ae7cacc --- /dev/null +++ b/components/01-atoms/SwappingIcons.tsx @@ -0,0 +1,109 @@ +import { useTheme } from "next-themes"; +import { useRouter } from "next/router"; +import { useState } from "react"; +import { + SwappingIcon, + OffersIcon, + ChatIcon, + NotificationsIcon, +} from "@/components/01-atoms/icons"; +import cc from "classcat"; + +export interface IconSwap { + id: number; + name: string; + href: string; + icon: React.ReactNode; +} + +export enum SwappingIconsID { + "SWAPLACE_STATION", + "OFFERS", + "CHAT", + "NOTIFICATIONS", +} + +export const SwappingIcons = () => { + const { theme } = useTheme(); + const [isActiveTab, setIsActiveTab] = useState( + SwappingIconsID.SWAPLACE_STATION + ); + + const swappingTabs: Array = [ + { + id: SwappingIconsID.SWAPLACE_STATION, + name: "Swaplace Station", + href: "/", + icon: ( + + ), + }, + { + id: SwappingIconsID.OFFERS, + name: "Offers", + href: "/offers", + icon: ( + + ), + }, + { + id: SwappingIconsID.CHAT, + name: "Chat", + href: "/", + icon: ( + + ), + }, + { + id: SwappingIconsID.NOTIFICATIONS, + name: "Notifications", + href: "/", + icon: ( + + ), + }, + ]; + + const router = useRouter(); + const handleClick = (e: IconSwap) => { + setIsActiveTab(e.id); + router.push(e.href); + }; + + return ( + <> + {swappingTabs.map((swapIcons) => { + return ( +
{ + handleClick(swapIcons); + }} + > +
+ {swapIcons.icon} +
+
+ ); + })} + + ); +}; diff --git a/components/01-atoms/icons/ChatIcon.tsx b/components/01-atoms/icons/ChatIcon.tsx new file mode 100644 index 00000000..ea420aa7 --- /dev/null +++ b/components/01-atoms/icons/ChatIcon.tsx @@ -0,0 +1,22 @@ +import { SVGProps } from "react"; + +export const ChatIcon = (props: SVGProps) => { + return ( + + + + + + ); +}; diff --git a/components/01-atoms/icons/NotificationsIcon.tsx b/components/01-atoms/icons/NotificationsIcon.tsx new file mode 100644 index 00000000..7b355411 --- /dev/null +++ b/components/01-atoms/icons/NotificationsIcon.tsx @@ -0,0 +1,22 @@ +import { SVGProps } from "react"; + +export const NotificationsIcon = (props: SVGProps) => { + return ( + + + + + + ); +}; diff --git a/components/01-atoms/icons/OffersIcon.tsx b/components/01-atoms/icons/OffersIcon.tsx new file mode 100644 index 00000000..81908e35 --- /dev/null +++ b/components/01-atoms/icons/OffersIcon.tsx @@ -0,0 +1,22 @@ +import { SVGProps } from "react"; + +export const OffersIcon = (props: SVGProps) => { + return ( + + + + + + ); +}; diff --git a/components/01-atoms/icons/SwappingIcon.tsx b/components/01-atoms/icons/SwappingIcon.tsx new file mode 100644 index 00000000..fa715eb0 --- /dev/null +++ b/components/01-atoms/icons/SwappingIcon.tsx @@ -0,0 +1,22 @@ +import { SVGProps } from "react"; + +export const SwappingIcon = (props: SVGProps) => { + return ( + + + + + + ); +}; diff --git a/components/01-atoms/icons/index.tsx b/components/01-atoms/icons/index.tsx index 7a2f2796..4bd5b2d1 100644 --- a/components/01-atoms/icons/index.tsx +++ b/components/01-atoms/icons/index.tsx @@ -1,10 +1,14 @@ +export * from "./ChatIcon"; export * from "./DangerIcon"; export * from "./EthereumIcon"; export * from "./MagnifyingGlassIcon"; +export * from "./NotificationsIcon"; +export * from "./OffersIcon"; export * from "./PaperPlane"; export * from "./PersonIcon"; export * from "./PolygonIcon"; export * from "./SelectUserIcon"; export * from "./SwapIcon"; export * from "./SwaplaceIcon"; +export * from "./SwappingIcon"; export * from "./WalletIcon"; diff --git a/components/01-atoms/index.ts b/components/01-atoms/index.ts index 0355c2c5..57ac5b33 100644 --- a/components/01-atoms/index.ts +++ b/components/01-atoms/index.ts @@ -1,9 +1,10 @@ export * from "./ConnectWallet"; export * from "./SearchBar"; export * from "./SelectAuthedUserChain"; -export * from "./Tab"; -export * from "./SwapContext"; export * from "./SelectDestinyChain"; export * from "./ConfirmSwapModal"; export * from "./TransactionResultModal"; export * from "./LoadingIndicator"; +export * from "./SwapContext"; +export * from "./SwappingIcons"; +export * from "./Tab"; diff --git a/components/02-molecules/CardHome.tsx b/components/02-molecules/CardHome.tsx index ff440e52..4e97e37c 100644 --- a/components/02-molecules/CardHome.tsx +++ b/components/02-molecules/CardHome.tsx @@ -8,14 +8,14 @@ export const CardHome = () => {
-

Swaplace

+

Swaplace

-
+
Your greatest deals are here
-
+
Connect your wallet to start swapping your NFTs and tokens
@@ -23,7 +23,7 @@ export const CardHome = () => {
diff --git a/components/02-molecules/TheHeader.tsx b/components/02-molecules/TheHeader.tsx index 17714bca..22e97f9d 100644 --- a/components/02-molecules/TheHeader.tsx +++ b/components/02-molecules/TheHeader.tsx @@ -3,8 +3,9 @@ import cc from "classcat"; import { useScreenSize } from "@/lib/client/hooks/useScreenSize"; import { useAuthenticatedUser } from "@/lib/client/hooks/useAuthenticatedUser"; import { useTheme } from "next-themes"; -import { ConnectWallet } from "@/components/01-atoms"; +import { ConnectWallet, SwappingIcons } from "@/components/01-atoms"; import { SwaplaceIcon, WalletIcon } from "@/components/01-atoms/icons/"; +import Link from "next/link"; export const TheHeader = () => { const { isDesktop } = useScreenSize(); @@ -28,15 +29,22 @@ export const TheHeader = () => { const currentTheme = theme === "system" ? systemTheme : theme; return ( -
- -
- +
+
+ + + +
+ +
+
+
+
-
+
{currentTheme === "dark" ? (
, )} ) : nftData.contract.name && nftData.id.tokenId ? ( @@ -138,7 +138,7 @@ export const NftCard = ({ {ButtonLayout(
{nftData.metadata?.name} -
+
, )} ) : null; diff --git a/components/02-molecules/OfferSummary.tsx b/components/02-molecules/OfferSummary.tsx index 633b7d57..fdb47eae 100644 --- a/components/02-molecules/OfferSummary.tsx +++ b/components/02-molecules/OfferSummary.tsx @@ -38,7 +38,7 @@ export const OfferSummary = ({ forAuthedUser }: IOfferSummary) => { data ? data : new EthereumAddress( - validatedAddressToSwap + validatedAddressToSwap, ).getEllipsedAddress() } gives`}

diff --git a/components/02-molecules/SwapStation.tsx b/components/02-molecules/SwapStation.tsx index 1831bf6b..31e02d7c 100644 --- a/components/02-molecules/SwapStation.tsx +++ b/components/02-molecules/SwapStation.tsx @@ -13,7 +13,7 @@ export const SwapStation = () => { useEffect(() => { setIsValidSwap( - !!nftAuthUser.length && !!nftInputUser.length && !!validatedAddressToSwap + !!nftAuthUser.length && !!nftInputUser.length && !!validatedAddressToSwap, ); }, [nftAuthUser, nftInputUser, validatedAddressToSwap]); @@ -34,7 +34,7 @@ export const SwapStation = () => { if (!nftInputUser.length) { toast.error( - "You must select at least one NFT from the destiny wallet to swap" + "You must select at least one NFT from the destiny wallet to swap", ); return; } diff --git a/components/02-molecules/TheHeader.tsx b/components/02-molecules/TheHeader.tsx index 22e97f9d..1c294e44 100644 --- a/components/02-molecules/TheHeader.tsx +++ b/components/02-molecules/TheHeader.tsx @@ -11,7 +11,7 @@ export const TheHeader = () => { const { isDesktop } = useScreenSize(); const { authenticatedUserAddress } = useAuthenticatedUser(); const [showFullNav, setShowFullNav] = useState( - !isDesktop && !!authenticatedUserAddress?.address + !isDesktop && !!authenticatedUserAddress?.address, ); useEffect(() => { diff --git a/components/03-organisms/NftsShelf.tsx b/components/03-organisms/NftsShelf.tsx index fcbda686..0afc15db 100644 --- a/components/03-organisms/NftsShelf.tsx +++ b/components/03-organisms/NftsShelf.tsx @@ -24,7 +24,7 @@ export const NftsShelf = ({ address }: INftsShelfProps) => { const { chain } = useNetwork(); const [nftsList, setNftsList] = useState(); const [nftsQueryStatus, setNftsQueryStatus] = useState( - NFTsQueryStatus.EMPTY_QUERY + NFTsQueryStatus.EMPTY_QUERY, ); const { theme } = useTheme(); diff --git a/lib/client/blockchain-data.ts b/lib/client/blockchain-data.ts index cfa28081..b7ccfe3b 100644 --- a/lib/client/blockchain-data.ts +++ b/lib/client/blockchain-data.ts @@ -7,7 +7,7 @@ import { getTimestamp } from "./utils"; export const getNftsFrom = async ( address: string, chainId: number, - stateSetter: Dispatch> + stateSetter: Dispatch>, ) => { const baseUrl = getRpcHttpUrlForNetwork.get(chainId); @@ -52,12 +52,12 @@ export async function makeConfig( Contract: any, allowed: any, destinationChainSelector: any, - expiration: any + expiration: any, ) { const config = await Contract.packData( allowed, destinationChainSelector, - expiration + expiration, ); return config; } @@ -70,7 +70,7 @@ export async function makeSwap( expiration: any, biding: NFT[], asking: NFT[], - chainId: number + chainId: number, ) { const timestamp = await getTimestamp(chainId); if (expiration < timestamp) { @@ -85,7 +85,7 @@ export async function makeSwap( Contract, allowed, destinationChainSelector, - expiration + expiration, ); const swap: Swap = { diff --git a/lib/client/hooks/useAuthenticatedUser.tsx b/lib/client/hooks/useAuthenticatedUser.tsx index 8e12048c..bd86dbb5 100644 --- a/lib/client/hooks/useAuthenticatedUser.tsx +++ b/lib/client/hooks/useAuthenticatedUser.tsx @@ -67,7 +67,7 @@ export const useAuthenticatedUser = (): AuthenticatedUserHook => { setAuthenticatedAccountAddress( accountAuthenticated && address ? new EthereumAddress(address.toLowerCase()) - : null + : null, ); setLoadingAuthenticatedUser(false); }, [nextAuthUser, isConnected, address]); diff --git a/lib/client/hooks/useScreenSize.tsx b/lib/client/hooks/useScreenSize.tsx index f9342b6c..f4b1785c 100644 --- a/lib/client/hooks/useScreenSize.tsx +++ b/lib/client/hooks/useScreenSize.tsx @@ -13,16 +13,16 @@ export const useScreenSize = () => { const checkIfIsMobile = () => { setIsMobile( - window.matchMedia(`(max-width: ${TABLET_SCREEN_SIZE - 1}px)`).matches + window.matchMedia(`(max-width: ${TABLET_SCREEN_SIZE - 1}px)`).matches, ); setIsTablet( - window.matchMedia(`(max-width: ${DESKTOP_SCREEN_SIZE - 1}px)`).matches + window.matchMedia(`(max-width: ${DESKTOP_SCREEN_SIZE - 1}px)`).matches, ); setIsDesktop( - window.matchMedia(`(min-width: ${DESKTOP_SCREEN_SIZE}px)`).matches + window.matchMedia(`(min-width: ${DESKTOP_SCREEN_SIZE}px)`).matches, ); setIsWideScreen( - window.matchMedia(`(min-width: ${WIDE_SCREEN_SIZE}px)`).matches + window.matchMedia(`(min-width: ${WIDE_SCREEN_SIZE}px)`).matches, ); }; diff --git a/lib/shared/types.ts b/lib/shared/types.ts index 5deb5b2e..609c4681 100644 --- a/lib/shared/types.ts +++ b/lib/shared/types.ts @@ -1,7 +1,7 @@ export class EthereumAddress { static readonly ETHEREUM_ADDRESS_LENGTH = 40; static readonly pattern = new RegExp( - `^0x[a-fA-F0-9]{${EthereumAddress.ETHEREUM_ADDRESS_LENGTH}}$` + `^0x[a-fA-F0-9]{${EthereumAddress.ETHEREUM_ADDRESS_LENGTH}}$`, ); private readonly _value: string; diff --git a/lib/wallet/wallet-config.ts b/lib/wallet/wallet-config.ts index 760b9042..3088e022 100644 --- a/lib/wallet/wallet-config.ts +++ b/lib/wallet/wallet-config.ts @@ -20,7 +20,7 @@ export const { chains, webSocketPublicClient, publicClient } = configureChains( http: getRpcHttpUrlForNetwork.get(chain.id) ?? "", }), }), - ] + ], ); const connectorArgs = { From d1aeb6874f959002325acedee7d9f26e168d12d6 Mon Sep 17 00:00:00 2001 From: heronlancellot Date: Tue, 19 Dec 2023 17:09:38 -0300 Subject: [PATCH 06/94] feat: add CONTRIBUTING.MD --- CONTRIBUTING.md | 76 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..30a5b284 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,76 @@ +# Contribution Guidelines + +Thank you for your interest in contributing to Swaplace! The project is an open source build by the community. We are welcome any type of contribution, suggestion or improvement, no matter how small. + +### Contents + +- [Open Source Guideline](#how-to-contribute) +- [Opening an Issue](#opening-issue) +- [Writing Commit Messages](#writing-commit-messages) +- [Submitting Pull Requests](#submiting-pull-requests) +- [Code Review](#code-review) +- [Coding Style](#coding-style) +- [Get in touch](#get-in-touch) + +## How to Contribute + +There are many ways to contribute, but here are a few steps to start: + +1. Fork the repository in GitHub +2. Check if you have any issue, suggestion or improvement to work in. + + - We manage all the issues using [GitHub Projects](https://github.com/orgs/blockful-io/projects/3) + +3. Send a message in the issue like + `I'm interested in this issue` or ask for more information like `Hey, can you provide more information about this ... ?`and the mantainers will assigned or provide more context about your issue. **After that, you are asigned to the issue.** + +4. If a task is already assigned but you believe you can expedite the process, feel free to comment, requesting to assist or speed up the task. Additionally, you may open a pull request directly because we prioritize both code efficiency and delivery speed. Thus, we encourage multiple individuals to review the same issues and debate together to enhance the code's security. + +### Congratulations ! Now you can start work in the issue and everyone knows you are assigned. + +## Opening Issue + +Before opening an issue, please check if there is no issue open. If there is, feel free to comment or suggest more details. We are always open to feedback and receptive to suggestions! + +- Before [creating an issue](https://docs.github.com/en/issues/tracking-your-work-with-issues/creating-an-issue#creating-an-issue-from-a-project), check if your fork is updated. + +## Writing Commit Messages + +We are using [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) + +Some examples below: + +- feat: adds or remove a new feature +- fix: fixes a bug +- refactor: rewrite/restructure your code +- chore: changes to the build process or auxiliary tools and libraries such as documentation generation +- style: changes do not affect the meaning (white-space, formatting, missing semi-colons, etc) +- test: add missing tests or correcting existing tests +- docs: affect documentation only + +## Submiting Pull Requests + +You can resolve an issue and after that submit a pull request fixing an issue and remember to [reference that issue](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword#linking-a-pull-request-to-an-issue-using-a-keyword). When submit a PR, put the code below with the number of the issue you are closing +`Example: closes #1` + +## Code Review + +The maintainers will review your PR. If something is missing or a fix needs to be made, the maintainers will let you know in the PR comment. + +## Coding Style + +In Swaplace please use this .prettierrc.yml configuration to make the code standardized. + +``` +{ + trailingComma: "all" + singleQuote: false + printWidth: 80 + tabWidth: 2 + semi: true +} +``` + +## Get in Touch + +If you need to get in contact with the repository maintainers, please reach out in our [Discord](https://discord.gg/B6uDmm7hvC). From 06430297d975cea37ec8b688da6855c345966bd8 Mon Sep 17 00:00:00 2001 From: heronlancellot Date: Wed, 20 Dec 2023 15:05:56 -0300 Subject: [PATCH 07/94] feat: add empty-cards add empty cards in offer-sumary & nfts-list --- components/02-molecules/NftCard.tsx | 2 +- components/02-molecules/NftsList.tsx | 47 ++++++++--- components/02-molecules/OfferSummary.tsx | 56 ++++++++++---- components/02-molecules/SwapStation.tsx | 2 +- components/03-organisms/NftsShelf.tsx | 90 +++++++++++----------- components/03-organisms/SwappingShelfs.tsx | 7 ++ components/04-templates/SwapSection.tsx | 2 +- lib/client/constants.ts | 5 ++ styles/global.css | 4 + 9 files changed, 142 insertions(+), 73 deletions(-) diff --git a/components/02-molecules/NftCard.tsx b/components/02-molecules/NftCard.tsx index 37db1cbd..897a81da 100644 --- a/components/02-molecules/NftCard.tsx +++ b/components/02-molecules/NftCard.tsx @@ -100,7 +100,7 @@ export const NftCard = ({ diff --git a/components/01-atoms/EmptyNftsCards.tsx b/components/01-atoms/EmptyNftsCards.tsx new file mode 100644 index 00000000..788d2736 --- /dev/null +++ b/components/01-atoms/EmptyNftsCards.tsx @@ -0,0 +1,31 @@ +import { useScreenSize } from "@/lib/client/hooks/useScreenSize"; + +export const EmptyNftsCards = ( + len: number, + ismobileTotalSquares: number, + isWideScreenTotalSquares: number, + isDesktopTotalSquares: number, + isTabletTotalSquares: number, +) => { + const { isDesktop, isTablet, isWideScreen, isMobile } = useScreenSize(); + + let totalSquares: number = 0; + + isMobile + ? (totalSquares = ismobileTotalSquares) + : isWideScreen + ? (totalSquares = isWideScreenTotalSquares) + : isDesktop + ? (totalSquares = isDesktopTotalSquares) + : isTablet && (totalSquares = isTabletTotalSquares); + + const emptySquaresCount = Math.max(totalSquares - len, 0); + + const emptySquares = Array.from({ length: emptySquaresCount }, (_, index) => ( + <> +
+ + )); + + return emptySquares; +}; diff --git a/components/01-atoms/SwapContext.tsx b/components/01-atoms/SwapContext.tsx index 4a3f8675..8fd70de2 100644 --- a/components/01-atoms/SwapContext.tsx +++ b/components/01-atoms/SwapContext.tsx @@ -19,6 +19,8 @@ interface SwapContextProps { nftInputUser: NFT[]; destinyChain: SupportedNetworks; setDestinyChain: Dispatch>; + setTimeDate: Dispatch>; + timeDate: bigint; } export const SwapContext = React.createContext({ @@ -37,6 +39,8 @@ export const SwapContext = React.createContext({ nftInputUser: [], destinyChain: SupportedNetworks.SEPOLIA, setDestinyChain: () => {}, + setTimeDate: () => {}, + timeDate: BigInt(1), }); export const SwapContextProvider = ({ children }: any) => { @@ -48,6 +52,7 @@ export const SwapContextProvider = ({ children }: any) => { const [destinyChain, setDestinyChain] = useState( SupportedNetworks.SEPOLIA, ); + const [timeDate, setTimeDate] = useState(BigInt(1)); const validateAddressToSwap = ( _authedUser: EthereumAddress, @@ -121,6 +126,8 @@ export const SwapContextProvider = ({ children }: any) => { nftInputUser, destinyChain, setDestinyChain, + setTimeDate, + timeDate, }); }, [ inputAddress, @@ -129,6 +136,7 @@ export const SwapContextProvider = ({ children }: any) => { nftAuthUser, nftInputUser, destinyChain, + timeDate, ]); const [swapData, setSwapData] = useState({ @@ -144,6 +152,8 @@ export const SwapContextProvider = ({ children }: any) => { nftInputUser, destinyChain, setDestinyChain, + setTimeDate, + timeDate, }); return ( diff --git a/components/01-atoms/SwapExpireTime.tsx b/components/01-atoms/SwapExpireTime.tsx new file mode 100644 index 00000000..915a30b9 --- /dev/null +++ b/components/01-atoms/SwapExpireTime.tsx @@ -0,0 +1,68 @@ +import React, { useContext, useEffect, useState } from "react"; +import { useNetwork } from "wagmi"; +import { SwapContext } from "."; +import { TimeStampDate, ExpireDate } from "@/lib/client/constants"; +import { getTimestamp } from "@/lib/client/utils"; + +export const SwapExpireTime = () => { + const { chain } = useNetwork(); + const { setTimeDate } = useContext(SwapContext); + const [selectedOption, setSelectedOption] = useState( + TimeStampDate.ONE_DAY, + ); + + let chainID: number; + + if (typeof chain?.id !== "undefined") { + chainID = chain.id; + } + + const fetchData = async (selectedValue: TimeStampDate) => { + try { + const timeSelected = BigInt(selectedValue); + const timestamp = await getTimestamp(chainID); + setTimeDate(timeSelected + timestamp); + } catch (error) { + console.error("error", error); + } + }; + + const handleSelectChange = (event: React.ChangeEvent) => { + const selectedValue = event.target.value as unknown as TimeStampDate; + setSelectedOption(selectedValue); + fetchData(selectedValue); + }; + + useEffect(() => { + fetchData(selectedOption); + }, [selectedOption]); + + return ( +
+
+
+ Expires in +
+
+
+ +
+
+
+
+ ); +}; diff --git a/components/01-atoms/index.ts b/components/01-atoms/index.ts index dd21187c..d7356e82 100644 --- a/components/01-atoms/index.ts +++ b/components/01-atoms/index.ts @@ -1,4 +1,5 @@ export * from "./ConnectWallet"; +export * from "./EmptyNftsCards"; export * from "./StatusOffers"; export * from "./SearchBar"; export * from "./SelectAuthedUserChain"; @@ -7,5 +8,6 @@ export * from "./ConfirmSwapModal"; export * from "./TransactionResultModal"; export * from "./LoadingIndicator"; export * from "./SwapContext"; +export * from "./SwapExpireTime"; export * from "./SwappingIcons"; export * from "./Tab"; diff --git a/components/02-molecules/NftsList.tsx b/components/02-molecules/NftsList.tsx index e29334c6..1c2e6e99 100644 --- a/components/02-molecules/NftsList.tsx +++ b/components/02-molecules/NftsList.tsx @@ -1,6 +1,6 @@ import { INftsList, NFT } from "@/lib/client/constants"; import { NftCard } from "@/components/02-molecules"; -import { useScreenSize } from "@/lib/client/hooks/useScreenSize"; +import { EmptyNftsCards } from "@/components/01-atoms"; /** * @@ -12,7 +12,7 @@ import { useScreenSize } from "@/lib/client/hooks/useScreenSize"; */ export const NftsList = ({ nftsList, ownerAddress }: INftsList) => { - const emptySquares = EmptyNftsCards(nftsList.length); + const emptySquares = EmptyNftsCards(nftsList.length, 15, 30, 30, 30); const nftSquares = nftsList.map((nft: NFT, index) => (
@@ -27,27 +27,3 @@ export const NftsList = ({ nftsList, ownerAddress }: INftsList) => {
); }; - -const EmptyNftsCards = (len: number) => { - const { isDesktop, isTablet, isWideScreen, isMobile } = useScreenSize(); - - let totalSquares: number = 0; - - isMobile - ? (totalSquares = 15) - : isWideScreen - ? (totalSquares = 30) - : isDesktop - ? (totalSquares = 30) - : isTablet && (totalSquares = 30); - - const emptySquaresCount = Math.max(totalSquares - len, 0); - - const emptySquares = Array.from({ length: emptySquaresCount }, (_, index) => ( - <> -
- - )); - - return emptySquares; -}; diff --git a/components/02-molecules/OfferSummary.tsx b/components/02-molecules/OfferSummary.tsx index 0f53eb09..af7e8582 100644 --- a/components/02-molecules/OfferSummary.tsx +++ b/components/02-molecules/OfferSummary.tsx @@ -6,7 +6,7 @@ import { ChainInfo } from "@/lib/client/constants"; import { SwapContext } from "@/components/01-atoms"; import { PersonIcon } from "@/components/01-atoms/icons"; import { NftCard } from "@/components/02-molecules"; -import { useScreenSize } from "@/lib/client/hooks/useScreenSize"; +import { EmptyNftsCards } from "@/components/01-atoms"; interface IOfferSummary { forAuthedUser: boolean; @@ -21,8 +21,14 @@ export const OfferSummary = ({ forAuthedUser }: IOfferSummary) => { }); const { authenticatedUserAddress } = useAuthenticatedUser(); - const emptySquaresAuthUser = EmptyNftsCards(nftAuthUser.length); - const emptySquaresInputUser = EmptyNftsCards(nftInputUser.length); + const emptySquaresAuthUser = EmptyNftsCards(nftAuthUser.length, 4, 8, 12, 12); + const emptySquaresInputUser = EmptyNftsCards( + nftInputUser.length, + 4, + 8, + 12, + 12, + ); return (
@@ -97,26 +103,3 @@ export const OfferSummary = ({ forAuthedUser }: IOfferSummary) => {
); }; - -const EmptyNftsCards = (len: number) => { - const { isDesktop, isTablet, isWideScreen, isMobile } = useScreenSize(); - - let totalSquares: number = 0; - isMobile - ? (totalSquares = 4) - : isWideScreen - ? (totalSquares = 8) - : isDesktop - ? (totalSquares = 12) - : isTablet && (totalSquares = 12); - - const emptySquaresCount = Math.max(totalSquares - len, 0); - - const emptySquares = Array.from({ length: emptySquaresCount }, (_, index) => ( - <> -
- - )); - - return emptySquares; -}; diff --git a/components/02-molecules/SwapStation.tsx b/components/02-molecules/SwapStation.tsx index 50524e4b..24e95a52 100644 --- a/components/02-molecules/SwapStation.tsx +++ b/components/02-molecules/SwapStation.tsx @@ -4,6 +4,7 @@ import { PaperPlane } from "@/components/01-atoms/icons"; import { OfferSummary } from "@/components/02-molecules"; import cc from "classcat"; import toast from "react-hot-toast"; +import { SwapExpireTime } from "@/components/01-atoms/SwapExpireTime"; export const SwapStation = () => { const [isValidSwap, setIsValidSwap] = useState(false); @@ -46,9 +47,16 @@ export const SwapStation = () => { return (
-

- Swap offer -

+
+
+

+ Swap offer +

+
+
+ +
+
diff --git a/lib/client/abi.ts b/lib/client/abi.ts new file mode 100644 index 00000000..7793a71c --- /dev/null +++ b/lib/client/abi.ts @@ -0,0 +1,446 @@ +export const SwaplaceAbi = [ + { + inputs: [ + { + internalType: "address", + name: "caller", + type: "address", + }, + ], + name: "InvalidAddress", + type: "error", + }, + { + inputs: [], + name: "InvalidAssetsLength", + type: "error", + }, + { + inputs: [ + { + internalType: "uint256", + name: "timestamp", + type: "uint256", + }, + ], + name: "InvalidExpiry", + type: "error", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "uint256", + name: "id", + type: "uint256", + }, + { + indexed: true, + internalType: "address", + name: "acceptee", + type: "address", + }, + ], + name: "SwapAccepted", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "uint256", + name: "id", + type: "uint256", + }, + { + indexed: true, + internalType: "address", + name: "owner", + type: "address", + }, + ], + name: "SwapCanceled", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "uint256", + name: "id", + type: "uint256", + }, + { + indexed: true, + internalType: "address", + name: "owner", + type: "address", + }, + { + indexed: true, + internalType: "uint256", + name: "expiry", + type: "uint256", + }, + ], + name: "SwapCreated", + type: "event", + }, + { + inputs: [ + { + internalType: "uint256", + name: "id", + type: "uint256", + }, + ], + name: "acceptSwap", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "id", + type: "uint256", + }, + ], + name: "cancelSwap", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + components: [ + { + internalType: "address", + name: "owner", + type: "address", + }, + { + internalType: "address", + name: "allowed", + type: "address", + }, + { + internalType: "uint256", + name: "expiry", + type: "uint256", + }, + { + components: [ + { + internalType: "address", + name: "addr", + type: "address", + }, + { + internalType: "uint256", + name: "amountOrId", + type: "uint256", + }, + ], + internalType: "struct ISwap.Asset[]", + name: "biding", + type: "tuple[]", + }, + { + components: [ + { + internalType: "address", + name: "addr", + type: "address", + }, + { + internalType: "uint256", + name: "amountOrId", + type: "uint256", + }, + ], + internalType: "struct ISwap.Asset[]", + name: "asking", + type: "tuple[]", + }, + ], + internalType: "struct ISwap.Swap", + name: "swap", + type: "tuple", + }, + ], + name: "createSwap", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "id", + type: "uint256", + }, + ], + name: "getSwap", + outputs: [ + { + components: [ + { + internalType: "address", + name: "owner", + type: "address", + }, + { + internalType: "address", + name: "allowed", + type: "address", + }, + { + internalType: "uint256", + name: "expiry", + type: "uint256", + }, + { + components: [ + { + internalType: "address", + name: "addr", + type: "address", + }, + { + internalType: "uint256", + name: "amountOrId", + type: "uint256", + }, + ], + internalType: "struct ISwap.Asset[]", + name: "biding", + type: "tuple[]", + }, + { + components: [ + { + internalType: "address", + name: "addr", + type: "address", + }, + { + internalType: "uint256", + name: "amountOrId", + type: "uint256", + }, + ], + internalType: "struct ISwap.Asset[]", + name: "asking", + type: "tuple[]", + }, + ], + internalType: "struct ISwap.Swap", + name: "", + type: "tuple", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "addr", + type: "address", + }, + { + internalType: "uint256", + name: "amountOrId", + type: "uint256", + }, + ], + name: "makeAsset", + outputs: [ + { + components: [ + { + internalType: "address", + name: "addr", + type: "address", + }, + { + internalType: "uint256", + name: "amountOrId", + type: "uint256", + }, + ], + internalType: "struct ISwap.Asset", + name: "", + type: "tuple", + }, + ], + stateMutability: "pure", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "owner", + type: "address", + }, + { + internalType: "address", + name: "allowed", + type: "address", + }, + { + internalType: "uint256", + name: "expiry", + type: "uint256", + }, + { + components: [ + { + internalType: "address", + name: "addr", + type: "address", + }, + { + internalType: "uint256", + name: "amountOrId", + type: "uint256", + }, + ], + internalType: "struct ISwap.Asset[]", + name: "biding", + type: "tuple[]", + }, + { + components: [ + { + internalType: "address", + name: "addr", + type: "address", + }, + { + internalType: "uint256", + name: "amountOrId", + type: "uint256", + }, + ], + internalType: "struct ISwap.Asset[]", + name: "asking", + type: "tuple[]", + }, + ], + name: "makeSwap", + outputs: [ + { + components: [ + { + internalType: "address", + name: "owner", + type: "address", + }, + { + internalType: "address", + name: "allowed", + type: "address", + }, + { + internalType: "uint256", + name: "expiry", + type: "uint256", + }, + { + components: [ + { + internalType: "address", + name: "addr", + type: "address", + }, + { + internalType: "uint256", + name: "amountOrId", + type: "uint256", + }, + ], + internalType: "struct ISwap.Asset[]", + name: "biding", + type: "tuple[]", + }, + { + components: [ + { + internalType: "address", + name: "addr", + type: "address", + }, + { + internalType: "uint256", + name: "amountOrId", + type: "uint256", + }, + ], + internalType: "struct ISwap.Asset[]", + name: "asking", + type: "tuple[]", + }, + ], + internalType: "struct ISwap.Swap", + name: "", + type: "tuple", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "bytes4", + name: "interfaceID", + type: "bytes4", + }, + ], + name: "supportsInterface", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "pure", + type: "function", + }, + { + inputs: [], + name: "totalSwaps", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, +] as const; diff --git a/lib/client/blockchain-data.ts b/lib/client/blockchain-data.ts index b7ccfe3b..1e7167a8 100644 --- a/lib/client/blockchain-data.ts +++ b/lib/client/blockchain-data.ts @@ -1,9 +1,17 @@ -import { ethers } from "ethers"; import { Dispatch, SetStateAction } from "react"; import { NFT, NFTsQueryStatus, getRpcHttpUrlForNetwork } from "./constants"; -import { publicClient } from "../wallet/wallet-config"; import { getTimestamp } from "./utils"; +export interface Swapping { + walletClient: any; + expireDate: bigint; + nftInputUser: any; + nftAuthUser: any; + validatedAddressToSwap: string; + authenticatedUserAddress: any; + chain: number; +} + export const getNftsFrom = async ( address: string, chainId: number, diff --git a/lib/client/constants.ts b/lib/client/constants.ts index 2d4d2778..7ffff4bf 100644 --- a/lib/client/constants.ts +++ b/lib/client/constants.ts @@ -26,6 +26,7 @@ export enum NFTsQueryStatus { export enum SupportedNetworks { SEPOLIA = "SEPOLIA", MUMBAI = "MUMBAI", + HARDHAT = "HARDHAT", } interface ChainProps { @@ -42,14 +43,47 @@ export const ChainInfo: Record = { id: 80001, name: "Polygon Mumbai", }, + [SupportedNetworks.HARDHAT]: { + id: 31337, + name: "Hardhat", + }, }; export let getRpcHttpUrlForNetwork: Map = new Map([ [ChainInfo.SEPOLIA.id, process.env.NEXT_PUBLIC_ALCHEMY_SEPOLIA_HTTP ?? ""], [ChainInfo.MUMBAI.id, process.env.NEXT_PUBLIC_ALCHEMY_MUMBAI_HTTP ?? ""], + [ChainInfo.HARDHAT.id, "http://127.0.0.1:8545/"], ]); export const SWAPLACE_SMART_CONTRACT_ADDRESS = { - [ChainInfo.SEPOLIA.id]: "0xcB003ed4Df4679D15b8863BB8F7609855A6a380d", + [ChainInfo.HARDHAT.id]: "0x8A791620dd6260079BF849Dc5567aDC3F2FdC318", + [ChainInfo.SEPOLIA.id]: "0xD8E3580C1b6f117c5b35DdD01dd9e50d9487501D", [ChainInfo.MUMBAI.id]: "0xcB003ed4Df4679D15b8863BB8F7609855A6a380d", }; + +export enum TimeStampDate { + ONE_DAY = 24 * 60 * 60 * 1000, + ONE_WEEK = ONE_DAY * 7, + ONE_MONTH = ONE_WEEK * 4, + SIX_MONTH = ONE_MONTH * 6, + ONE_YEAR = SIX_MONTH * 2, +} + +export const ONE_DAY = 24 * 60 * 60 * 1000; +export const ONE_WEEK = ONE_DAY * 7; +export const ONE_MONTH = ONE_WEEK * 4; +export const SIX_MONTH = ONE_MONTH * 6; +export const ONE_YEAR = SIX_MONTH * 2; + +export interface ExpireOption { + label: string; + value: TimeStampDate; +} + +export const ExpireDate: ExpireOption[] = [ + { label: "1 Day", value: ONE_DAY }, + { label: "7 Days", value: ONE_WEEK }, + { label: "1 Month", value: ONE_MONTH }, + { label: "6 Month", value: SIX_MONTH }, + { label: "1 Year", value: ONE_YEAR }, +]; diff --git a/lib/client/utils.ts b/lib/client/utils.ts index e1248827..83664f16 100644 --- a/lib/client/utils.ts +++ b/lib/client/utils.ts @@ -19,4 +19,5 @@ export const getTimestamp = async (chainId: number) => { const blockDetails = await provider.getBlock({ blockNumber: block }); const timestamp = blockDetails.timestamp; + return timestamp; }; diff --git a/lib/service/creatingSwap.ts b/lib/service/creatingSwap.ts new file mode 100644 index 00000000..f199c4f6 --- /dev/null +++ b/lib/service/creatingSwap.ts @@ -0,0 +1,39 @@ +import { SwaplaceAbi } from "../client/abi"; +import { Swapping } from "../client/blockchain-data"; +import { SWAPLACE_SMART_CONTRACT_ADDRESS } from "../client/constants"; +import { hexToNumber } from "viem"; + +export function creatingSwap({ + walletClient, + expireDate, + nftInputUser, + nftAuthUser, + validatedAddressToSwap, + authenticatedUserAddress, + chain, +}: Swapping) { + return walletClient?.writeContract({ + abi: SwaplaceAbi, + functionName: "createSwap", + args: [ + { + owner: authenticatedUserAddress.address as `0x${string}`, + allowed: validatedAddressToSwap as `0x${string}`, + expiry: expireDate, + biding: [ + { + addr: nftAuthUser.contract.address, + amountOrId: hexToNumber(nftAuthUser.id.tokenId), + }, + ], + asking: [ + { + addr: nftInputUser.contract.address, + amountOrId: hexToNumber(nftInputUser.id.tokenId), + }, + ], + }, + ], + address: SWAPLACE_SMART_CONTRACT_ADDRESS[chain] as `0x${string}`, + }); +} diff --git a/lib/wallet/wallet-config.ts b/lib/wallet/wallet-config.ts index 3088e022..351273e9 100644 --- a/lib/wallet/wallet-config.ts +++ b/lib/wallet/wallet-config.ts @@ -1,4 +1,4 @@ -import { polygonMumbai, sepolia } from "@wagmi/core/chains"; +import { polygonMumbai, sepolia, hardhat } from "@wagmi/core/chains"; import { configureChains, createConfig } from "wagmi"; import { trustWallet, @@ -13,7 +13,7 @@ import { jsonRpcProvider } from "wagmi/providers/jsonRpc"; import { getRpcHttpUrlForNetwork } from "../client/constants"; export const { chains, webSocketPublicClient, publicClient } = configureChains( - [sepolia, polygonMumbai], + [sepolia, polygonMumbai, hardhat], [ jsonRpcProvider({ rpc: (chain) => ({ @@ -25,7 +25,7 @@ export const { chains, webSocketPublicClient, publicClient } = configureChains( const connectorArgs = { appName: "Swaplace dApp", - chains: [sepolia, polygonMumbai], + chains: [sepolia, polygonMumbai, hardhat], projectId: process.env.NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID ?? "", }; From 5ddcdd56aa11098c9c30213ca6bf301368e32b8f Mon Sep 17 00:00:00 2001 From: heronlancellot Date: Wed, 27 Dec 2023 18:46:59 -0300 Subject: [PATCH 10/94] feat: add create-swap-n-n - refactor frontend v1 - remove chains ids - adjust the select time - add create swap n-n - adjust design --- components/01-atoms/ConfirmSwapModal.tsx | 17 ++-- components/01-atoms/SearchBar.tsx | 21 +---- components/01-atoms/SwapExpireTime.tsx | 6 +- components/02-molecules/NftCard.tsx | 60 ++++++++------ components/02-molecules/OfferSummary.tsx | 49 +++++------- lib/client/abi.ts | 33 ++++++-- lib/client/blockchain-data.ts | 39 +++++++++- lib/service/creatingSwap.ts | 99 +++++++++++++++++++----- lib/wallet/wallet-config.ts | 6 ++ styles/global.css | 2 +- 10 files changed, 223 insertions(+), 109 deletions(-) diff --git a/components/01-atoms/ConfirmSwapModal.tsx b/components/01-atoms/ConfirmSwapModal.tsx index aee4b747..471c0dac 100644 --- a/components/01-atoms/ConfirmSwapModal.tsx +++ b/components/01-atoms/ConfirmSwapModal.tsx @@ -6,7 +6,7 @@ import { SwapContext, TransactionResultModal } from "@/components/01-atoms"; import { NftCard, NftCardActionType } from "@/components/02-molecules"; import { SwapIcon } from "@/components/01-atoms/icons"; import { creatingSwap } from "@/lib/service/creatingSwap"; -import { Swapping } from "@/lib/client/blockchain-data"; +import { ComposeNftSwap, ICreateSwap } from "@/lib/client/blockchain-data"; interface ConfirmSwapModalProps { open: boolean; @@ -49,23 +49,30 @@ export const ConfirmSwapModal = ({ open, onClose }: ConfirmSwapModalProps) => { return null; } + const nftsInputUser = ComposeNftSwap(nftInputUser); + const nftsAuthUser = ComposeNftSwap(nftAuthUser); + let chainId: number; const handleOffer = () => { if (typeof chain?.id != "undefined") { chainId = chain?.id; } - const swapData: Swapping = { + const swapData: ICreateSwap = { walletClient: walletClient, expireDate: timeDate, - nftInputUser: nftInputUser[0], - nftAuthUser: nftAuthUser[0], + nftInputUser: nftsInputUser, + nftAuthUser: nftsAuthUser, validatedAddressToSwap: validatedAddressToSwap, authenticatedUserAddress: authenticatedUserAddress, chain: chainId, }; - return creatingSwap(swapData); + try { + creatingSwap(swapData); + } catch (error) { + console.error(error); + } }; return ( diff --git a/components/01-atoms/SearchBar.tsx b/components/01-atoms/SearchBar.tsx index 94e65c45..2e8f33a0 100644 --- a/components/01-atoms/SearchBar.tsx +++ b/components/01-atoms/SearchBar.tsx @@ -1,11 +1,7 @@ import cc from "classcat"; import { useContext, useEffect, useState } from "react"; import { MagnifyingGlassIcon } from "@/components/01-atoms/icons"; -import { - SelectAuthedUserChain, - SelectDestinyChain, - SwapContext, -} from "@/components/01-atoms"; +import { SwapContext } from "@/components/01-atoms"; import { useAuthenticatedUser } from "@/lib/client/hooks/useAuthenticatedUser"; import { ENS } from "web3-eth-ens"; import Web3 from "web3"; @@ -131,21 +127,6 @@ export const SearchBar = () => {
- -
-
-

Your network:

- -
-
-

- Searched address network: -

-
- -
-
-
); }; diff --git a/components/01-atoms/SwapExpireTime.tsx b/components/01-atoms/SwapExpireTime.tsx index 915a30b9..65949cb9 100644 --- a/components/01-atoms/SwapExpireTime.tsx +++ b/components/01-atoms/SwapExpireTime.tsx @@ -40,7 +40,7 @@ export const SwapExpireTime = () => { return (
-
+
Expires in
@@ -48,13 +48,13 @@ export const SwapExpireTime = () => { +
+
+
+ +
+
+ ); +}; + +const TokenBody = () => { + enum TokenPosibilities { + ERC20 = "ERC20", + ERC721 = "ERC721", + } + + type TokenPossibilites = TokenPosibilities | "ERC20" | "ERC721"; + + const [token, setToken] = useState("ERC20"); + return ( +
+
+
What kind of token you want to add?
+
+ + +
+
+
+ {token === "ERC20" ? ( +
+
Contract address
+
+ +
+
+ ) : ( +
+
+
Contract address
+
+ +
+
+
+
Token ID
+
+ +
+
+
+ )} +
+
+ +
+
+ ); +}; + +const AddManuallyVariantConfig: Record = + { + [AddManuallyVariant.SWAP]: { + header: "Add swap manually", + body: , + }, + [AddManuallyVariant.TOKEN]: { + header: "Add token", + body: , + }, + }; + +export const SwapAddManuallyModalLayout = ({ + variant = AddManuallyVariant.TOKEN, +}: AddManuallyProps) => { + const [openModal, setOpenModal] = useState(false); + const { theme } = useTheme(); + return ( +
+
+
+ {AddManuallyVariantConfig[variant].header} +
+
{ + setOpenModal(!openModal); + }} + > + +
+
+
{AddManuallyVariantConfig[variant].body}
+
+ ); +}; diff --git a/components/01-atoms/SwapModalLayout.tsx b/components/01-atoms/SwapModalLayout.tsx index 7592c7fa..9109ec35 100644 --- a/components/01-atoms/SwapModalLayout.tsx +++ b/components/01-atoms/SwapModalLayout.tsx @@ -76,11 +76,7 @@ export const SwapModalLayout = ({

{text.title}

-
+
diff --git a/components/01-atoms/icons/CloseIcon.tsx b/components/01-atoms/icons/CloseIcon.tsx index b8570295..ae0f93a2 100644 --- a/components/01-atoms/icons/CloseIcon.tsx +++ b/components/01-atoms/icons/CloseIcon.tsx @@ -2,21 +2,23 @@ import { SVGProps } from "react"; export const CloseIcon = (props: SVGProps) => { return ( - - - - - +
+ + + + + +
); }; diff --git a/styles/global.css b/styles/global.css index 292f3620..9bda1c48 100644 --- a/styles/global.css +++ b/styles/global.css @@ -15,6 +15,13 @@ input[type="search"]::-webkit-search-results-decoration { @tailwind utilities; @layer utilities { + .shadow-add-manually-card { + box-shadow: 0px 0px 12px 1px #00000066; + } + .shadow-add-manually-button { + box-shadow: 0px 0px 6px 1px rgba(0, 0, 0, 0.3); + } + .title-h1 { } @@ -65,6 +72,9 @@ input[type="search"]::-webkit-search-results-decoration { @apply font-onest font-medium text-[16px] leading-[20px] text-[#F6F6F6]; } + .p-medium-bold-variant-black { + @apply font-onest font-medium text-[14px] leading-[16px] text-[#181A19]; + } .p-medium-bold { @apply font-onest font-medium text-[14px] leading-[16px] text-[#707572]; } From 70dbcb8c423a482ff2cc681d78f01456da43b074 Mon Sep 17 00:00:00 2001 From: heronlancellot Date: Thu, 15 Feb 2024 14:22:11 -0300 Subject: [PATCH 55/94] feat: add open&close & resize to mobile devices --- .../01-atoms/SwapAddManuallyModalLayout.tsx | 38 +++++++++++-------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/components/01-atoms/SwapAddManuallyModalLayout.tsx b/components/01-atoms/SwapAddManuallyModalLayout.tsx index 39e628df..36428da1 100644 --- a/components/01-atoms/SwapAddManuallyModalLayout.tsx +++ b/components/01-atoms/SwapAddManuallyModalLayout.tsx @@ -1,4 +1,5 @@ import { CloseIcon } from "./icons/CloseIcon"; +import { useScreenSize } from "@/lib/client/hooks/useScreenSize"; import React, { useState } from "react"; import cc from "classcat"; import { useTheme } from "next-themes"; @@ -17,6 +18,8 @@ interface AddManuallyConfig { interface AddManuallyProps { variant?: Variant; + open: boolean; + onClose: () => void; } const SwapBody = () => { @@ -127,26 +130,31 @@ const AddManuallyVariantConfig: Record = export const SwapAddManuallyModalLayout = ({ variant = AddManuallyVariant.TOKEN, + open, + onClose, }: AddManuallyProps) => { - const [openModal, setOpenModal] = useState(false); const { theme } = useTheme(); + const { isMobile } = useScreenSize(); return ( -
-
-
- {AddManuallyVariantConfig[variant].header} -
+ <> + {open && (
{ - setOpenModal(!openModal); - }} + className={cc([ + "dark:bg-[#212322] min-h-[256px] min-w-[400px] border rounded-[20px] border-[#353836] shadow-add-manually-card", + isMobile && "min-w-[90%] w-[300px]", + ])} > - +
+
+ {AddManuallyVariantConfig[variant].header} +
+
+ +
+
+
{AddManuallyVariantConfig[variant].body}
-
-
{AddManuallyVariantConfig[variant].body}
-
+ )} + ); }; From c3d5ca10604eae1544af27d008493090f5e55a7d Mon Sep 17 00:00:00 2001 From: heronlancellot Date: Thu, 15 Feb 2024 15:32:53 -0300 Subject: [PATCH 56/94] feat: add light/dark mode in component --- .../01-atoms/SwapAddManuallyModalLayout.tsx | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/components/01-atoms/SwapAddManuallyModalLayout.tsx b/components/01-atoms/SwapAddManuallyModalLayout.tsx index 36428da1..5ef906dc 100644 --- a/components/01-atoms/SwapAddManuallyModalLayout.tsx +++ b/components/01-atoms/SwapAddManuallyModalLayout.tsx @@ -28,7 +28,7 @@ const SwapBody = () => {
Swap ID
- +
@@ -56,10 +56,10 @@ const TokenBody = () => {
From a0e010cc47f699d2911c5741bed7c1fdc739d50d Mon Sep 17 00:00:00 2001 From: heronlancellot Date: Thu, 15 Feb 2024 16:50:58 -0300 Subject: [PATCH 57/94] feat:add background opacity when open dialog --- .../01-atoms/SwapAddManuallyModalLayout.tsx | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/components/01-atoms/SwapAddManuallyModalLayout.tsx b/components/01-atoms/SwapAddManuallyModalLayout.tsx index 5ef906dc..3fb53d47 100644 --- a/components/01-atoms/SwapAddManuallyModalLayout.tsx +++ b/components/01-atoms/SwapAddManuallyModalLayout.tsx @@ -136,11 +136,16 @@ export const SwapAddManuallyModalLayout = ({ const { theme } = useTheme(); const { isMobile } = useScreenSize(); return ( - <> - {open && ( + +
@@ -154,7 +159,7 @@ export const SwapAddManuallyModalLayout = ({
{AddManuallyVariantConfig[variant].body}
- )} - +
+ ); }; From e182315eca2fbb6918b44fd58ecec544d7f5a227 Mon Sep 17 00:00:00 2001 From: heronlancellot Date: Thu, 15 Feb 2024 17:03:38 -0300 Subject: [PATCH 58/94] update: text color in light mode --- components/01-atoms/SwapAddManuallyModalLayout.tsx | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/components/01-atoms/SwapAddManuallyModalLayout.tsx b/components/01-atoms/SwapAddManuallyModalLayout.tsx index 3fb53d47..16507d5a 100644 --- a/components/01-atoms/SwapAddManuallyModalLayout.tsx +++ b/components/01-atoms/SwapAddManuallyModalLayout.tsx @@ -26,7 +26,7 @@ const SwapBody = () => { return (
-
Swap ID
+
Swap ID
@@ -85,7 +85,9 @@ const TokenBody = () => {
{token === "ERC20" ? (
-
Contract address
+
+ Contract address +
@@ -93,13 +95,17 @@ const TokenBody = () => { ) : (
-
Contract address
+
+ Contract address +
-
Token ID
+
+ Token ID +
From 485ff6355e6e17412ae225b86dce191ace8e48a6 Mon Sep 17 00:00:00 2001 From: heronlancellot Date: Thu, 15 Feb 2024 17:05:37 -0300 Subject: [PATCH 59/94] update: globals css --- styles/global.css | 3 +++ 1 file changed, 3 insertions(+) diff --git a/styles/global.css b/styles/global.css index 9bda1c48..c08b39e7 100644 --- a/styles/global.css +++ b/styles/global.css @@ -89,6 +89,9 @@ input[type="search"]::-webkit-search-results-decoration { @apply font-onest font-medium text-[14px] leading-[20px] text-[#F6F6F6]; } + .p-small-variant-black { + @apply font-onest font-normal text-[14px] leading-[20px] text-[#181A19]; + } .p-small { @apply font-onest font-normal text-[14px] leading-[20px] text-[#707572]; } From f3a7023680a0b8e599717f8ca5f2bcb6ea08c3e9 Mon Sep 17 00:00:00 2001 From: eduramme Date: Thu, 15 Feb 2024 17:15:10 -0300 Subject: [PATCH 60/94] fix header --- components/01-atoms/ConnectWallet.tsx | 2 +- components/01-atoms/SwappingIcons.tsx | 30 +++++------ components/02-molecules/TheHeader.tsx | 2 +- package-lock.json | 72 ++++++++++++++++++--------- 4 files changed, 66 insertions(+), 40 deletions(-) diff --git a/components/01-atoms/ConnectWallet.tsx b/components/01-atoms/ConnectWallet.tsx index 1bb47c30..677e6485 100644 --- a/components/01-atoms/ConnectWallet.tsx +++ b/components/01-atoms/ConnectWallet.tsx @@ -1,6 +1,6 @@ +import { WalletIcon } from "./icons"; import { ConnectButton } from "@rainbow-me/rainbowkit"; import { useRouter } from "next/router"; -import { WalletIcon } from "./icons"; interface IConnectWallet { customStyle?: string; diff --git a/components/01-atoms/SwappingIcons.tsx b/components/01-atoms/SwappingIcons.tsx index b015bca8..e9c3a2b9 100644 --- a/components/01-atoms/SwappingIcons.tsx +++ b/components/01-atoms/SwappingIcons.tsx @@ -86,52 +86,52 @@ export const SwappingIcons = () => { }; return ( -
- {swappingTabs.map((swapIcons) => { + <> + {swappingTabs.map((swapIcon) => { return ( - <> +
{isWideScreen ? ( - +
{ - handleClick(swapIcons); + handleClick(swapIcon); }} >
- {swapIcons.icon} + {swapIcon.icon}
) : ( - +
{ - handleClick(swapIcons); + handleClick(swapIcon); }} >
- {swapIcons.icon} + {swapIcon.icon}
)} - + ); })} -
+ ); }; diff --git a/components/02-molecules/TheHeader.tsx b/components/02-molecules/TheHeader.tsx index 4e433aad..40a2b808 100644 --- a/components/02-molecules/TheHeader.tsx +++ b/components/02-molecules/TheHeader.tsx @@ -6,7 +6,7 @@ import { SwappingIcons, Tooltip, } from "@/components/01-atoms"; -import { SwaplaceIcon, WalletIcon } from "@/components/01-atoms/icons/"; +import { SwaplaceIcon } from "@/components/01-atoms/icons/"; import { useTheme } from "next-themes"; import React, { useEffect, useState } from "react"; import Link from "next/link"; diff --git a/package-lock.json b/package-lock.json index 33885b94..1fe38235 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,7 @@ "@rainbow-me/rainbowkit": "^1.3.0", "@rainbow-me/rainbowkit-siwe-next-auth": "0.1.8", "@typescript-eslint/eslint-plugin": "5.54.1", - "addreth": "^1.2.0", + "axios": "^1.6.7", "boring-avatars": "1.7.0", "classcat": "^5.0.4", "eslint-plugin-unused-imports": "2.0.0", @@ -37,6 +37,7 @@ "@types/react-dom": "^18", "@typescript-eslint/parser": "^6.13.1", "autoprefixer": "^10.0.1", + "dotenv": "^16.4.1", "eslint": "^8", "eslint-config-next": "14.0.3", "postcss": "^8", @@ -3256,21 +3257,6 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/addreth": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/addreth/-/addreth-1.2.0.tgz", - "integrity": "sha512-LwO7aIqE+yEK6o6sCqyjRiJoRL4JZEAb3AuC5pAK6GvCXlpR+YziE2vaHshs/62MhNqB/q39/VDbXTgKF/pP6A==", - "peerDependencies": { - "react": ">=18.0.0", - "react-dom": ">=18.0.0", - "wagmi": ">=1.4.0" - }, - "peerDependenciesMeta": { - "wagmi": { - "optional": true - } - } - }, "node_modules/aes-js": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.1.2.tgz", @@ -3529,8 +3515,7 @@ "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, "node_modules/atomic-sleep": { "version": "1.0.0", @@ -3597,6 +3582,16 @@ "node": ">=4" } }, + "node_modules/axios": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.7.tgz", + "integrity": "sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==", + "dependencies": { + "follow-redirects": "^1.15.4", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, "node_modules/axobject-query": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.2.1.tgz", @@ -4008,7 +4003,6 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, "dependencies": { "delayed-stream": "~1.0.0" }, @@ -4231,7 +4225,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "dev": true, "engines": { "node": ">=0.4.0" } @@ -4319,6 +4312,18 @@ "node": ">=6.0.0" } }, + "node_modules/dotenv": { + "version": "16.4.4", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.4.tgz", + "integrity": "sha512-XvPXc8XAQThSjAbY6cQ/9PcBXmFoWuw1sQ3b8HqUCR6ziGXjkTi//kB9SWa2UwqlgdAIuRqAa/9hVljzPehbYg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, "node_modules/duplexify": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", @@ -5339,6 +5344,25 @@ "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", "dev": true }, + "node_modules/follow-redirects": { + "version": "1.15.5", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz", + "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, "node_modules/for-each": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", @@ -5351,7 +5375,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dev": true, "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -6805,7 +6828,6 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, "engines": { "node": ">= 0.6" } @@ -6814,7 +6836,6 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, "dependencies": { "mime-db": "1.52.0" }, @@ -7756,6 +7777,11 @@ "resolved": "https://registry.npmjs.org/proxy-compare/-/proxy-compare-2.5.1.tgz", "integrity": "sha512-oyfc0Tx87Cpwva5ZXezSp5V9vht1c7dZBhvuV/y3ctkgMVUmiAGDVeeB0dKhGSyT0v1ZTEQYpe/RXlBVBNuCLA==" }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", From 71901d0c3e4b98d7960907a4c053d35e463599ff Mon Sep 17 00:00:00 2001 From: eduramme Date: Thu, 15 Feb 2024 17:16:37 -0300 Subject: [PATCH 61/94] fix icon errors --- components/01-atoms/icons/SelectUserIcon.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/components/01-atoms/icons/SelectUserIcon.tsx b/components/01-atoms/icons/SelectUserIcon.tsx index 135b3cff..73677def 100644 --- a/components/01-atoms/icons/SelectUserIcon.tsx +++ b/components/01-atoms/icons/SelectUserIcon.tsx @@ -14,9 +14,9 @@ export const SelectUserIcon = (props: SVGProps) => { id="Vector" d="M31.0187 35L34.023 38M15.997 38H5.18143C4.05971 38 3.49884 38 3.0704 37.782C2.69354 37.5902 2.38714 37.2844 2.1951 36.908C1.97681 36.4802 1.97681 35.9202 1.97681 34.8V31.3682C1.97681 30.097 1.97681 29.4612 2.0729 28.9312C2.51933 26.4688 4.44921 24.5418 6.91509 24.096C7.06915 24.0682 7.23179 24.0484 7.41616 24.0344C7.86689 24 8.09225 23.9828 8.39329 24.0052C8.70618 24.0286 8.88117 24.0594 9.18315 24.1444C9.47366 24.2262 9.99696 24.463 11.0435 24.9364C12.2655 25.4892 13.5966 25.8436 14.9956 25.959M32.0202 31C32.0202 33.7614 29.7783 36 27.0129 36C24.2475 36 22.0057 33.7614 22.0057 31C22.0057 28.2386 24.2475 26 27.0129 26C29.7783 26 32.0202 28.2386 32.0202 31ZM24.0086 10C24.0086 14.4183 20.4216 18 15.997 18C11.5724 18 7.98548 14.4183 7.98548 10C7.98548 5.58172 11.5724 2 15.997 2C20.4216 2 24.0086 5.58172 24.0086 10Z" stroke={props.fill ? props.fill : "#DDF23D"} - stroke-width="3" - stroke-linecap="round" - stroke-linejoin="round" + strokeWidth="3" + strokeLinecap="round" + strokeLinejoin="round" /> ); From 7cece72cc183e078a501bda00d5180fdb2dad145 Mon Sep 17 00:00:00 2001 From: eduramme Date: Thu, 15 Feb 2024 20:24:39 -0300 Subject: [PATCH 62/94] fix grid --- components/01-atoms/EmptyNftsCards.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/01-atoms/EmptyNftsCards.tsx b/components/01-atoms/EmptyNftsCards.tsx index 261bd50b..1398267c 100644 --- a/components/01-atoms/EmptyNftsCards.tsx +++ b/components/01-atoms/EmptyNftsCards.tsx @@ -23,7 +23,7 @@ export const EmptyNftsCards = ( const emptySquares = Array.from({ length: emptySquaresCount }, (_, index) => ( <> -
+
)); From 4c964c170654128d9153c9bf2b5a5da7941fab29 Mon Sep 17 00:00:00 2001 From: eduramme Date: Thu, 15 Feb 2024 20:27:33 -0300 Subject: [PATCH 63/94] fix active tba --- components/01-atoms/SwappingIcons.tsx | 2 +- pages/index.tsx | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/components/01-atoms/SwappingIcons.tsx b/components/01-atoms/SwappingIcons.tsx index bd6047cf..e0bb177c 100644 --- a/components/01-atoms/SwappingIcons.tsx +++ b/components/01-atoms/SwappingIcons.tsx @@ -48,7 +48,7 @@ export const SwappingIcons = () => { { id: SwappingIconsID.OFFERS, name: "Offers", - href: "/offers/", + href: "/offers", icon: OffersIcon, }, { diff --git a/pages/index.tsx b/pages/index.tsx index e870d87b..f385c389 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -1,6 +1,5 @@ import { TheHeader } from "@/components/02-molecules"; import { Layout, SwapSection } from "@/components/04-templates"; -import { useAuthenticatedUser } from "@/lib/client/hooks/useAuthenticatedUser"; import cc from "classcat"; export default function IndexPage() { From b545fd614d020c335aa33856ec1564107c775c0e Mon Sep 17 00:00:00 2001 From: heronlancellot Date: Fri, 16 Feb 2024 12:01:08 -0300 Subject: [PATCH 64/94] feat: add error finding swap offers component --- components/01-atoms/icons/ErrorIcon.tsx | 50 +++++++++++++++++++ components/01-atoms/icons/index.tsx | 1 + components/01-atoms/index.ts | 1 + .../02-molecules/ErrorFindingSwapOffers.tsx | 40 +++++++++++++++ components/02-molecules/index.tsx | 1 + components/04-templates/OfferSection.tsx | 11 ++-- styles/global.css | 3 ++ 7 files changed, 104 insertions(+), 3 deletions(-) create mode 100644 components/01-atoms/icons/ErrorIcon.tsx create mode 100644 components/02-molecules/ErrorFindingSwapOffers.tsx diff --git a/components/01-atoms/icons/ErrorIcon.tsx b/components/01-atoms/icons/ErrorIcon.tsx new file mode 100644 index 00000000..cd41ccf3 --- /dev/null +++ b/components/01-atoms/icons/ErrorIcon.tsx @@ -0,0 +1,50 @@ +import { SVGProps } from "react"; +import cc from "classcat"; +import { useTheme } from "next-themes"; + +export const ErrorIcon = (props: SVGProps) => { + const { theme } = useTheme(); + return ( +
+ + + + + + + + + + + +
+ ); +}; diff --git a/components/01-atoms/icons/index.tsx b/components/01-atoms/icons/index.tsx index acb487cf..6cd76f8c 100644 --- a/components/01-atoms/icons/index.tsx +++ b/components/01-atoms/icons/index.tsx @@ -1,6 +1,7 @@ export * from "./ChatIcon"; export * from "./CheckIcon"; export * from "./DangerIcon"; +export * from "./ErrorIcon"; export * from "./EthereumIcon"; export * from "./LeftIcon"; export * from "./MagnifyingGlassIcon"; diff --git a/components/01-atoms/index.ts b/components/01-atoms/index.ts index 05ef7e16..04a11bfb 100644 --- a/components/01-atoms/index.ts +++ b/components/01-atoms/index.ts @@ -8,6 +8,7 @@ export * from "./SearchBar"; export * from "./SelectAuthedUserChain"; export * from "./SelectDestinyChain"; export * from "./StatusOffers"; +export * from "./SwapAddManuallyModalLayout"; export * from "./SwapContext"; export * from "./SwapExpireTime"; export * from "./SwapModalButton"; diff --git a/components/02-molecules/ErrorFindingSwapOffers.tsx b/components/02-molecules/ErrorFindingSwapOffers.tsx new file mode 100644 index 00000000..7334201f --- /dev/null +++ b/components/02-molecules/ErrorFindingSwapOffers.tsx @@ -0,0 +1,40 @@ +import { SwapAddManuallyModalLayout } from "@/components/01-atoms"; +import { ErrorIcon } from "@/components/01-atoms/icons"; +import cc from "classcat"; +import { useTheme } from "next-themes"; +import { useState } from "react"; + +export const ErrorFindingSwapOffers = () => { + const { theme } = useTheme(); + const [toggleManually, setToggleManually] = useState(false); + return ( +
+
+ +
+
+

+ Sorry, we couldn't load your swaps +

+

+ Please try again later or add your swaps manually +

+
+
+ + { + setToggleManually(false); + }} + variant="swap" + /> +
+
+ ); +}; diff --git a/components/02-molecules/index.tsx b/components/02-molecules/index.tsx index 37ad81b6..cd264179 100644 --- a/components/02-molecules/index.tsx +++ b/components/02-molecules/index.tsx @@ -1,5 +1,6 @@ export * from "./CardHome"; export * from "./ConfirmSwapModal"; +export * from "./ErrorFindingSwapOffers"; export * from "./FilterOffers"; export * from "./NftCard"; export * from "./NftsList"; diff --git a/components/04-templates/OfferSection.tsx b/components/04-templates/OfferSection.tsx index dcc4ae3c..7c6eccb0 100644 --- a/components/04-templates/OfferSection.tsx +++ b/components/04-templates/OfferSection.tsx @@ -1,11 +1,16 @@ -import { FilterOffers } from "@/components/02-molecules"; +import { + ErrorFindingSwapOffers, + FilterOffers, +} from "@/components/02-molecules"; export const OfferSection = () => { return ( -
+
-
+
+
+
); diff --git a/styles/global.css b/styles/global.css index c08b39e7..56af0da6 100644 --- a/styles/global.css +++ b/styles/global.css @@ -71,6 +71,9 @@ input[type="search"]::-webkit-search-results-decoration { .p-medium-bold-2-dark { @apply font-onest font-medium text-[16px] leading-[20px] text-[#F6F6F6]; } + .p-medium-bold-2-dark-variant-black { + @apply font-onest font-medium text-[16px] leading-[20px] text-black; + } .p-medium-bold-variant-black { @apply font-onest font-medium text-[14px] leading-[16px] text-[#181A19]; From 936326a4f44d362755253b93d7cd00a34387897b Mon Sep 17 00:00:00 2001 From: heronlancellot Date: Fri, 16 Feb 2024 12:29:08 -0300 Subject: [PATCH 65/94] update: requested-changes --- components/01-atoms/icons/ErrorIcon.tsx | 8 +++++--- components/02-molecules/ErrorFindingSwapOffers.tsx | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/components/01-atoms/icons/ErrorIcon.tsx b/components/01-atoms/icons/ErrorIcon.tsx index cd41ccf3..ec9dd9a2 100644 --- a/components/01-atoms/icons/ErrorIcon.tsx +++ b/components/01-atoms/icons/ErrorIcon.tsx @@ -8,7 +8,9 @@ export const ErrorIcon = (props: SVGProps) => {
) => { diff --git a/components/02-molecules/ErrorFindingSwapOffers.tsx b/components/02-molecules/ErrorFindingSwapOffers.tsx index 7334201f..aeb4ec57 100644 --- a/components/02-molecules/ErrorFindingSwapOffers.tsx +++ b/components/02-molecules/ErrorFindingSwapOffers.tsx @@ -10,7 +10,7 @@ export const ErrorFindingSwapOffers = () => { return (
- +

From 924a564c6dd99a72f84756dbd2c8d26f53b1c492 Mon Sep 17 00:00:00 2001 From: Deepu Date: Fri, 16 Feb 2024 23:17:35 +0530 Subject: [PATCH 66/94] closes #125 --- components/01-atoms/SearchBar.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/01-atoms/SearchBar.tsx b/components/01-atoms/SearchBar.tsx index f7606530..10940022 100644 --- a/components/01-atoms/SearchBar.tsx +++ b/components/01-atoms/SearchBar.tsx @@ -81,7 +81,7 @@ export const SearchBar = () => { }, [loadingENSaddress]); return ( -

+

Who are you swapping with today? From 68ed85bded114762bddbbac6bc154285e52172c9 Mon Sep 17 00:00:00 2001 From: Deepu Date: Fri, 16 Feb 2024 23:36:09 +0530 Subject: [PATCH 67/94] Closes #125 --- components/01-atoms/SearchBar.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/01-atoms/SearchBar.tsx b/components/01-atoms/SearchBar.tsx index 10940022..50e6f6a5 100644 --- a/components/01-atoms/SearchBar.tsx +++ b/components/01-atoms/SearchBar.tsx @@ -81,7 +81,7 @@ export const SearchBar = () => { }, [loadingENSaddress]); return ( -
+

Who are you swapping with today? From 3a3a87e8cc201e5d5c32e8970ee4d5d4bfa70551 Mon Sep 17 00:00:00 2001 From: "frankind.eth" Date: Fri, 16 Feb 2024 15:30:57 -0300 Subject: [PATCH 68/94] Fixed copyright typo --- components/02-molecules/TheHeader.tsx | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/components/02-molecules/TheHeader.tsx b/components/02-molecules/TheHeader.tsx index c4857e2e..f7f2d4ba 100644 --- a/components/02-molecules/TheHeader.tsx +++ b/components/02-molecules/TheHeader.tsx @@ -34,7 +34,7 @@ export const TheHeader = () => { if (!mounted) return null; const currentTheme = theme === "system" ? systemTheme : theme; - const isDark = currentTheme === "dark" + const isDark = currentTheme === "dark"; return (
@@ -56,13 +56,19 @@ export const TheHeader = () => {
{isDark ? ( - - + ) : ( - - From 9b5981fa58c0821c545d627b4c10950a625f8134 Mon Sep 17 00:00:00 2001 From: "frankind.eth" Date: Fri, 16 Feb 2024 15:38:45 -0300 Subject: [PATCH 69/94] Fixed ENSAvatar component loading state --- components/01-atoms/ENSAvatar.tsx | 20 +++++++++++--------- lib/client/hooks/useENSData.tsx | 11 ++++++++--- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/components/01-atoms/ENSAvatar.tsx b/components/01-atoms/ENSAvatar.tsx index b361dcbf..68f17f7d 100644 --- a/components/01-atoms/ENSAvatar.tsx +++ b/components/01-atoms/ENSAvatar.tsx @@ -1,9 +1,11 @@ -import { EthereumAddress } from "@/lib/shared/types"; -import BoringAvatar from "boring-avatars"; import { ENSAvatarQueryStatus, useEnsData, } from "@/lib/client/hooks/useENSData"; +import { EthereumAddress } from "@/lib/shared/types"; +import BoringAvatar from "boring-avatars"; +import cc from "classcat"; +import { LoadingIndicator } from "."; enum ENSAvatarSize { SMALL = "small", @@ -31,13 +33,13 @@ export const ENSAvatar = ({ return (
{avatarQueryStatus === ENSAvatarQueryStatus.LOADING ? ( -
- +
+
) : avatarQueryStatus === ENSAvatarQueryStatus.ERROR ? (
diff --git a/lib/client/hooks/useENSData.tsx b/lib/client/hooks/useENSData.tsx index bbd16880..ec1fe53d 100644 --- a/lib/client/hooks/useENSData.tsx +++ b/lib/client/hooks/useENSData.tsx @@ -1,7 +1,7 @@ +import { EthereumAddress } from "@/lib/shared/types"; import { createPublicClient, http } from "viem"; import { useEffect, useState } from "react"; import { mainnet } from "viem/chains"; -import { EthereumAddress } from "@/lib/shared/types"; export enum ENSAvatarQueryStatus { LOADING, @@ -17,6 +17,8 @@ export const useEnsData = ({ ensAddress }: Props) => { const [primaryName, setPrimaryName] = useState( undefined, ); + const [avatarQueryStatus, setAvatarQueryStatus] = + useState(ENSAvatarQueryStatus.LOADING); useEffect(() => { if (ensAddress) { @@ -25,15 +27,18 @@ export const useEnsData = ({ ensAddress }: Props) => { transport: http(), }); + setAvatarQueryStatus(ENSAvatarQueryStatus.LOADING); + mainnetClient .getEnsName({ address: ensAddress.address as `0x${string}`, }) .then((name) => { - console.log(name); + setAvatarQueryStatus(ENSAvatarQueryStatus.SUCCESS); setPrimaryName(name); }) .catch(() => { + setAvatarQueryStatus(ENSAvatarQueryStatus.ERROR); setPrimaryName(null); }); } else { @@ -43,7 +48,7 @@ export const useEnsData = ({ ensAddress }: Props) => { return { primaryName, - avatarQueryStatus: ENSAvatarQueryStatus.LOADING, + avatarQueryStatus: avatarQueryStatus, avatarSrc: primaryName ? `https://metadata.ens.domains/mainnet/avatar/${primaryName}` : null, From a218835b6a6a9410c0583faabdbfad5ca30c61ab Mon Sep 17 00:00:00 2001 From: "frankind.eth" Date: Fri, 16 Feb 2024 15:40:53 -0300 Subject: [PATCH 70/94] Fixed lint issues --- components/01-atoms/ENSAvatar.tsx | 2 +- lib/client/hooks/subgraphQueries.ts | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/components/01-atoms/ENSAvatar.tsx b/components/01-atoms/ENSAvatar.tsx index 68f17f7d..742f4d91 100644 --- a/components/01-atoms/ENSAvatar.tsx +++ b/components/01-atoms/ENSAvatar.tsx @@ -1,3 +1,4 @@ +import { LoadingIndicator } from "."; import { ENSAvatarQueryStatus, useEnsData, @@ -5,7 +6,6 @@ import { import { EthereumAddress } from "@/lib/shared/types"; import BoringAvatar from "boring-avatars"; import cc from "classcat"; -import { LoadingIndicator } from "."; enum ENSAvatarSize { SMALL = "small", diff --git a/lib/client/hooks/subgraphQueries.ts b/lib/client/hooks/subgraphQueries.ts index 6c3e65db..112a34a9 100644 --- a/lib/client/hooks/subgraphQueries.ts +++ b/lib/client/hooks/subgraphQueries.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-var-requires */ require("dotenv").config(); import axios from "axios"; From 5b8bb0a1c4e6d8995b54669430e55a8ff2751ad3 Mon Sep 17 00:00:00 2001 From: "frankind.eth" Date: Fri, 16 Feb 2024 16:33:03 -0300 Subject: [PATCH 71/94] Installed ethers --- package-lock.json | 188 ++++++++++++++++++++++++++++++++++++++++++++++ package.json | 7 +- 2 files changed, 192 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index c667d93a..dbda7fe1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,6 +17,7 @@ "boring-avatars": "1.7.0", "classcat": "^5.0.4", "eslint-plugin-unused-imports": "2.0.0", + "ethers": "^6.11.1", "next": "14.0.3", "next-auth": "^4.20.1", "next-themes": "^0.2.1", @@ -444,6 +445,126 @@ "node": ">= 10" } }, + "node_modules/@next/swc-darwin-x64": { + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.0.3.tgz", + "integrity": "sha512-RkTf+KbAD0SgYdVn1XzqE/+sIxYGB7NLMZRn9I4Z24afrhUpVJx6L8hsRnIwxz3ERE2NFURNliPjJ2QNfnWicQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-gnu": { + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.0.3.tgz", + "integrity": "sha512-3tBWGgz7M9RKLO6sPWC6c4pAw4geujSwQ7q7Si4d6bo0l6cLs4tmO+lnSwFp1Tm3lxwfMk0SgkJT7EdwYSJvcg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-musl": { + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.0.3.tgz", + "integrity": "sha512-v0v8Kb8j8T23jvVUWZeA2D8+izWspeyeDGNaT2/mTHWp7+37fiNfL8bmBWiOmeumXkacM/AB0XOUQvEbncSnHA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-gnu": { + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.0.3.tgz", + "integrity": "sha512-VM1aE1tJKLBwMGtyBR21yy+STfl0MapMQnNrXkxeyLs0GFv/kZqXS5Jw/TQ3TSUnbv0QPDf/X8sDXuMtSgG6eg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-musl": { + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.0.3.tgz", + "integrity": "sha512-64EnmKy18MYFL5CzLaSuUn561hbO1Gk16jM/KHznYP3iCIfF9e3yULtHaMy0D8zbHfxset9LTOv6cuYKJgcOxg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-arm64-msvc": { + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.0.3.tgz", + "integrity": "sha512-WRDp8QrmsL1bbGtsh5GqQ/KWulmrnMBgbnb+59qNTW1kVi1nG/2ndZLkcbs2GX7NpFLlToLRMWSQXmPzQm4tog==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-ia32-msvc": { + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.0.3.tgz", + "integrity": "sha512-EKffQeqCrj+t6qFFhIFTRoqb2QwX1mU7iTOvMyLbYw3QtqTw9sMwjykyiMlZlrfm2a4fA84+/aeW+PMg1MjuTg==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-x64-msvc": { + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.0.3.tgz", + "integrity": "sha512-ERhKPSJ1vQrPiwrs15Pjz/rvDHZmkmvbf/BjPN/UCOI++ODftT0GtasDPi0j+y6PPJi5HsXw+dpRaXUaw4vjuQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, "node_modules/@noble/curves": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz", @@ -4019,6 +4140,73 @@ "url": "https://paulmillr.com/funding/" } }, + "node_modules/ethers": { + "version": "6.11.1", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.11.1.tgz", + "integrity": "sha512-mxTAE6wqJQAbp5QAe/+o+rXOID7Nw91OZXvgpjDa1r4fAbq2Nu314oEZSbjoRLacuCzs7kUC3clEvkCQowffGg==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/ethers-io/" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@adraffy/ens-normalize": "1.10.1", + "@noble/curves": "1.2.0", + "@noble/hashes": "1.3.2", + "@types/node": "18.15.13", + "aes-js": "4.0.0-beta.5", + "tslib": "2.4.0", + "ws": "8.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/ethers/node_modules/@adraffy/ens-normalize": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz", + "integrity": "sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==" + }, + "node_modules/ethers/node_modules/@types/node": { + "version": "18.15.13", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.13.tgz", + "integrity": "sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q==" + }, + "node_modules/ethers/node_modules/aes-js": { + "version": "4.0.0-beta.5", + "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-4.0.0-beta.5.tgz", + "integrity": "sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==" + }, + "node_modules/ethers/node_modules/tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" + }, + "node_modules/ethers/node_modules/ws": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", + "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/eventemitter3": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", diff --git a/package.json b/package.json index 320e862e..08bdc0b3 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "dev": "next dev", "build": "next build", "start": "next start", - "lint": "next lint" + "lint": "next lint --config .eslintrc" }, "dependencies": { "@headlessui-float/react": "^0.13.0", @@ -18,6 +18,7 @@ "boring-avatars": "1.7.0", "classcat": "^5.0.4", "eslint-plugin-unused-imports": "2.0.0", + "ethers": "^6.11.1", "next": "14.0.3", "next-auth": "^4.20.1", "next-themes": "^0.2.1", @@ -35,11 +36,11 @@ "@types/node-fetch": "^2.6.9", "@types/react": "^18", "@types/react-dom": "^18", - "eslint": "8.7.0", - "eslint-config-next": "13.4.19", "@typescript-eslint/eslint-plugin": "5.54.1", "autoprefixer": "^10.0.1", "dotenv": "^16.4.1", + "eslint": "8.7.0", + "eslint-config-next": "13.4.19", "postcss": "^8", "tailwindcss": "^3.3.0", "typescript": "^5" From d8106676769501d64a187bade88919f6c86d964e Mon Sep 17 00:00:00 2001 From: "frankind.eth" Date: Fri, 16 Feb 2024 18:45:07 -0300 Subject: [PATCH 72/94] Updated useENSData avatar query status setter --- lib/client/hooks/useENSData.tsx | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/client/hooks/useENSData.tsx b/lib/client/hooks/useENSData.tsx index ec1fe53d..ca50a076 100644 --- a/lib/client/hooks/useENSData.tsx +++ b/lib/client/hooks/useENSData.tsx @@ -34,8 +34,13 @@ export const useEnsData = ({ ensAddress }: Props) => { address: ensAddress.address as `0x${string}`, }) .then((name) => { - setAvatarQueryStatus(ENSAvatarQueryStatus.SUCCESS); - setPrimaryName(name); + if (name) { + setAvatarQueryStatus(ENSAvatarQueryStatus.SUCCESS); + setPrimaryName(name); + } else { + setAvatarQueryStatus(ENSAvatarQueryStatus.SUCCESS); + setPrimaryName(null); + } }) .catch(() => { setAvatarQueryStatus(ENSAvatarQueryStatus.ERROR); From b3e1f3b4d4eb2b6f9e0acf46ab2fe326d0115ef9 Mon Sep 17 00:00:00 2001 From: "frankind.eth" Date: Fri, 16 Feb 2024 19:00:39 -0300 Subject: [PATCH 73/94] Updated useENSData avatar query status setter --- lib/client/hooks/useENSData.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/client/hooks/useENSData.tsx b/lib/client/hooks/useENSData.tsx index ca50a076..88bbb548 100644 --- a/lib/client/hooks/useENSData.tsx +++ b/lib/client/hooks/useENSData.tsx @@ -38,7 +38,7 @@ export const useEnsData = ({ ensAddress }: Props) => { setAvatarQueryStatus(ENSAvatarQueryStatus.SUCCESS); setPrimaryName(name); } else { - setAvatarQueryStatus(ENSAvatarQueryStatus.SUCCESS); + setAvatarQueryStatus(ENSAvatarQueryStatus.ERROR); setPrimaryName(null); } }) From 9453a59f4cd30d2503ad0ad7b6d7cbe9123bf349 Mon Sep 17 00:00:00 2001 From: Blockchain User <90667119+0xneves@users.noreply.github.com> Date: Fri, 16 Feb 2024 19:14:34 -0300 Subject: [PATCH 74/94] feat: adding public project id for wallet connect client --- .env.example | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.env.example b/.env.example index 9a498d10..965ed868 100644 --- a/.env.example +++ b/.env.example @@ -1,4 +1,4 @@ -NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID= +NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID=50db9e195634356bb8ab0375a9f07607 NEXT_PUBLIC_ALCHEMY_SEPOLIA_HTTP= NEXT_PUBLIC_ALCHEMY_SEPOLIA_KEY= NEXT_PUBLIC_ALCHEMY_MUMBAI_HTTP= @@ -14,4 +14,4 @@ NEXT_PUBLIC_ALCHEMY_ETHEREUM_HTTP= ENDPOINT_URL=https://api.studio.thegraph.com/query/57887/swaplace-subgraph-sepolia/version/latest -AUTHORIZATION_KEY=3b2048f02febad918a35bbafe78b2115 \ No newline at end of file +AUTHORIZATION_KEY=3b2048f02febad918a35bbafe78b2115 From ea4436c62ab5dce91731c06a25a56d6339c4badd Mon Sep 17 00:00:00 2001 From: eduramme Date: Sat, 17 Feb 2024 08:16:38 -0300 Subject: [PATCH 75/94] create sidebar component --- components/01-atoms/WalletSidebarTemplate.tsx | 22 +++ components/01-atoms/index.ts | 1 + components/02-molecules/TheHeader.tsx | 170 ++++++++++-------- tailwind.config.ts | 4 +- 4 files changed, 119 insertions(+), 78 deletions(-) create mode 100644 components/01-atoms/WalletSidebarTemplate.tsx diff --git a/components/01-atoms/WalletSidebarTemplate.tsx b/components/01-atoms/WalletSidebarTemplate.tsx new file mode 100644 index 00000000..2d399416 --- /dev/null +++ b/components/01-atoms/WalletSidebarTemplate.tsx @@ -0,0 +1,22 @@ +import React from "react"; +import cc from "classcat"; + +interface WalletSidebarTemplateProps { + isOpen: boolean; + isMobile: boolean; +} + +export const WalletSidebarTemplate = ({ + isOpen, + isMobile, +}: WalletSidebarTemplateProps) => { + return ( +
+ ); +}; diff --git a/components/01-atoms/index.ts b/components/01-atoms/index.ts index fcbc8dd0..c8a6d893 100644 --- a/components/01-atoms/index.ts +++ b/components/01-atoms/index.ts @@ -24,3 +24,4 @@ export * from "./icons/SunIcon"; export * from "./icons/PaperPlane"; export * from "./icons/MagnifyingGlassIcon"; export * from "./icons/SelectUserIcon"; +export * from "./WalletSidebarTemplate"; diff --git a/components/02-molecules/TheHeader.tsx b/components/02-molecules/TheHeader.tsx index 421d7889..226dbc48 100644 --- a/components/02-molecules/TheHeader.tsx +++ b/components/02-molecules/TheHeader.tsx @@ -6,6 +6,7 @@ import { MoonIcon, SunIcon, Tooltip, + WalletSidebarTemplate, } from "@/components/01-atoms"; import { useScreenSize } from "@/lib/client/hooks/useScreenSize"; import { useAuthenticatedUser } from "@/lib/client/hooks/useAuthenticatedUser"; @@ -20,6 +21,12 @@ export const TheHeader = () => { const [showFullNav, setShowFullNav] = useState( !isDesktop && !!authenticatedUserAddress?.address, ); + const [isSidebarOpen, setIsSidebarOpen] = useState(false); + + const toggleSidebar = () => { + console.log("toggle"); + setIsSidebarOpen(!isSidebarOpen); + }; const { isWideScreen } = useScreenSize(); @@ -39,85 +46,94 @@ export const TheHeader = () => { const isDark = currentTheme === "dark"; return ( -
-
- - - -
- + <> +
+
+ + + +
+ +
-
-
- -
-
-
- {isDark ? ( - - - - ) : ( - - - - )} +
+
-
- {isWideScreen ? ( - <> - {!!authenticatedUserAddress ? ( - - - - ) : ( - -
- -
-
- )} - - ) : ( - <> - {!!authenticatedUserAddress ? ( - - - - ) : ( - -
- -
-
- )} - - )} +
+
+ {isDark ? ( + + + + ) : ( + + + + )} +
+
+ {isWideScreen ? ( + <> + {!!authenticatedUserAddress ? ( + + + + ) : ( + +
+ +
+
+ )} + + ) : ( + <> + {!!authenticatedUserAddress ? ( + + + + ) : ( + +
+ +
+
+ )} + + )} +
-
-
+
+ + ); }; diff --git a/tailwind.config.ts b/tailwind.config.ts index 1b153880..6c687625 100644 --- a/tailwind.config.ts +++ b/tailwind.config.ts @@ -12,9 +12,11 @@ const config: Config = { fontFamily: { onest: ["var(--font-onest)"], }, + boxShadow: { + custom: "0px 0px 12px 1px rgba(0, 0, 0, 0.40)", + }, }, }, - plugins: [], }; export default config; From 9509d60e79673b7c49b93a2ca854106bd5245d79 Mon Sep 17 00:00:00 2001 From: eduramme Date: Sat, 17 Feb 2024 08:49:46 -0300 Subject: [PATCH 76/94] apply blur on background --- components/01-atoms/WalletSidebarTemplate.tsx | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/components/01-atoms/WalletSidebarTemplate.tsx b/components/01-atoms/WalletSidebarTemplate.tsx index 2d399416..7cc5c07c 100644 --- a/components/01-atoms/WalletSidebarTemplate.tsx +++ b/components/01-atoms/WalletSidebarTemplate.tsx @@ -11,12 +11,21 @@ export const WalletSidebarTemplate = ({ isMobile, }: WalletSidebarTemplateProps) => { return ( + <> + {/*
*/} +
+ {/*
*/} +
+ + ); }; From a9d18775269f882930b2d81bab32025bb3335e14 Mon Sep 17 00:00:00 2001 From: eduramme Date: Sat, 17 Feb 2024 08:58:38 -0300 Subject: [PATCH 77/94] fix blur --- components/01-atoms/WalletSidebarTemplate.tsx | 36 +++++++++++-------- tailwind.config.ts | 3 +- 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/components/01-atoms/WalletSidebarTemplate.tsx b/components/01-atoms/WalletSidebarTemplate.tsx index 7cc5c07c..b5f450b3 100644 --- a/components/01-atoms/WalletSidebarTemplate.tsx +++ b/components/01-atoms/WalletSidebarTemplate.tsx @@ -1,5 +1,6 @@ import React from "react"; import cc from "classcat"; +import { useTheme } from "next-themes"; interface WalletSidebarTemplateProps { isOpen: boolean; @@ -10,22 +11,29 @@ export const WalletSidebarTemplate = ({ isOpen, isMobile, }: WalletSidebarTemplateProps) => { + const { systemTheme, theme } = useTheme(); + const currentTheme = theme === "system" ? systemTheme : theme; + const isDark = currentTheme === "dark"; + return ( <> - {/*
*/} -
- {/*
*/} - -
+
+ +
- ); }; diff --git a/tailwind.config.ts b/tailwind.config.ts index 6c687625..cd6c8c88 100644 --- a/tailwind.config.ts +++ b/tailwind.config.ts @@ -13,7 +13,8 @@ const config: Config = { onest: ["var(--font-onest)"], }, boxShadow: { - custom: "0px 0px 12px 1px rgba(0, 0, 0, 0.40)", + sidebarLight: "0px 0px 6px 1px rgba(0, 0, 0, 0.30)", + sidebarDark: "0px 0px 12px 1px rgba(0, 0, 0, 0.40)" }, }, }, From a9bf2afd249ed9568d1d54b7727a0446f08683bf Mon Sep 17 00:00:00 2001 From: eduramme Date: Sat, 17 Feb 2024 09:01:46 -0300 Subject: [PATCH 78/94] remove console log --- components/02-molecules/TheHeader.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/components/02-molecules/TheHeader.tsx b/components/02-molecules/TheHeader.tsx index 226dbc48..93822e19 100644 --- a/components/02-molecules/TheHeader.tsx +++ b/components/02-molecules/TheHeader.tsx @@ -24,7 +24,6 @@ export const TheHeader = () => { const [isSidebarOpen, setIsSidebarOpen] = useState(false); const toggleSidebar = () => { - console.log("toggle"); setIsSidebarOpen(!isSidebarOpen); }; From c3e4074cf51f345b884c6702001119214d14b1d6 Mon Sep 17 00:00:00 2001 From: Deepu Date: Sat, 17 Feb 2024 18:23:54 +0530 Subject: [PATCH 79/94] closes #128 --- .env.example | 2 +- lib/client/hooks/subgraphQueries.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.env.example b/.env.example index a7021669..ff90f7a4 100644 --- a/.env.example +++ b/.env.example @@ -14,4 +14,4 @@ NEXT_PUBLIC_ALCHEMY_ETHEREUM_HTTP= ENDPOINT_URL=https://api.studio.thegraph.com/query/57887/swaplace-subgraph-sepolia/version/latest -AUTHORIZATION_KEY=3b2048f02febad918a35bbafe78b2115 +SUBGRAPH_AUTH_KEY=3b2048f02febad918a35bbafe78b2115 diff --git a/lib/client/hooks/subgraphQueries.ts b/lib/client/hooks/subgraphQueries.ts index 112a34a9..19c618af 100644 --- a/lib/client/hooks/subgraphQueries.ts +++ b/lib/client/hooks/subgraphQueries.ts @@ -6,7 +6,7 @@ export const getGraphQuery = async () => { const endpoint = process.env.ENDPOINT_URL; const headers = { "content-type": "application/json", - Authorization: process.env.AUTHORIZATION_KEY, + Authorization: process.env.SUBGRAPH_AUTH_KEY, }; //Example of query From 9e696da779b8f1f396f833d0efb6fafc47318f1e Mon Sep 17 00:00:00 2001 From: eduramme Date: Sat, 17 Feb 2024 13:33:05 -0300 Subject: [PATCH 80/94] Create TheSidebarHeader for the WalletSidebarTemplate --- components/01-atoms/WalletSidebarTemplate.tsx | 5 ++++- components/02-molecules/TheSidebarHeader.tsx | 9 +++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 components/02-molecules/TheSidebarHeader.tsx diff --git a/components/01-atoms/WalletSidebarTemplate.tsx b/components/01-atoms/WalletSidebarTemplate.tsx index b5f450b3..52f1e277 100644 --- a/components/01-atoms/WalletSidebarTemplate.tsx +++ b/components/01-atoms/WalletSidebarTemplate.tsx @@ -1,3 +1,4 @@ +import { TheSidebarHeader } from "../02-molecules/TheSidebarHeader"; import React from "react"; import cc from "classcat"; import { useTheme } from "next-themes"; @@ -33,7 +34,9 @@ export const WalletSidebarTemplate = ({ isOpen ? "translate-x-0" : "translate-x-full", isMobile ? "w-full" : "w-[400px]", ])} - >
+ > + +
); }; diff --git a/components/02-molecules/TheSidebarHeader.tsx b/components/02-molecules/TheSidebarHeader.tsx new file mode 100644 index 00000000..ba8b2042 --- /dev/null +++ b/components/02-molecules/TheSidebarHeader.tsx @@ -0,0 +1,9 @@ +import React from "react"; + +export const TheSidebarHeader = () => { + return ( +
+ +
+ ); +}; From e4381ccb242d06233384b8324ee93e5e6817030a Mon Sep 17 00:00:00 2001 From: eduramme Date: Sat, 17 Feb 2024 14:13:22 -0300 Subject: [PATCH 81/94] create design --- .../01-atoms/SwapAddManuallyModalLayout.tsx | 2 +- components/01-atoms/SwapModalLayout.tsx | 2 +- components/01-atoms/icons/CloseIcon.tsx | 4 +- components/01-atoms/icons/PowerIcon.tsx | 26 +++++++++++++ components/02-molecules/TheSidebarHeader.tsx | 37 ++++++++++++++++++- 5 files changed, 65 insertions(+), 6 deletions(-) create mode 100644 components/01-atoms/icons/PowerIcon.tsx diff --git a/components/01-atoms/SwapAddManuallyModalLayout.tsx b/components/01-atoms/SwapAddManuallyModalLayout.tsx index 16507d5a..30f9606d 100644 --- a/components/01-atoms/SwapAddManuallyModalLayout.tsx +++ b/components/01-atoms/SwapAddManuallyModalLayout.tsx @@ -160,7 +160,7 @@ export const SwapAddManuallyModalLayout = ({ {AddManuallyVariantConfig[variant].header}
- +

{AddManuallyVariantConfig[variant].body}
diff --git a/components/01-atoms/SwapModalLayout.tsx b/components/01-atoms/SwapModalLayout.tsx index 9109ec35..9d31440c 100644 --- a/components/01-atoms/SwapModalLayout.tsx +++ b/components/01-atoms/SwapModalLayout.tsx @@ -78,7 +78,7 @@ export const SwapModalLayout = ({

diff --git a/components/01-atoms/icons/CloseIcon.tsx b/components/01-atoms/icons/CloseIcon.tsx index ae0f93a2..c7e9b65d 100644 --- a/components/01-atoms/icons/CloseIcon.tsx +++ b/components/01-atoms/icons/CloseIcon.tsx @@ -8,14 +8,14 @@ export const CloseIcon = (props: SVGProps) => { width="14" height="14" viewBox="0 0 14 14" - fill={props.fill ? props.fill : "black"} + fill={"currentColor"} xmlns="http://www.w3.org/2000/svg" > diff --git a/components/01-atoms/icons/PowerIcon.tsx b/components/01-atoms/icons/PowerIcon.tsx new file mode 100644 index 00000000..f76359b4 --- /dev/null +++ b/components/01-atoms/icons/PowerIcon.tsx @@ -0,0 +1,26 @@ +import { SVGProps } from "react"; + +export const PowerIcon = (props: SVGProps) => { + return ( + + + + + + + + + + + ); +}; diff --git a/components/02-molecules/TheSidebarHeader.tsx b/components/02-molecules/TheSidebarHeader.tsx index ba8b2042..235a2b9f 100644 --- a/components/02-molecules/TheSidebarHeader.tsx +++ b/components/02-molecules/TheSidebarHeader.tsx @@ -1,9 +1,42 @@ +import { CloseIcon } from "../01-atoms/icons/CloseIcon"; +import { PowerIcon } from "../01-atoms/icons/PowerIcon"; import React from "react"; +import cc from "classcat"; +import { useTheme } from "next-themes"; export const TheSidebarHeader = () => { - return ( -
+ const { systemTheme, theme } = useTheme(); + const currentTheme = theme === "system" ? systemTheme : theme; + const isDark = currentTheme === "dark"; + return ( +
+ +
+

+ Your wallet +

+
+ +

Disconnect

+
+
); }; From abc5277bd289284f97b9b61778c5a594181b7b3c Mon Sep 17 00:00:00 2001 From: eduramme Date: Sat, 17 Feb 2024 15:23:58 -0300 Subject: [PATCH 82/94] disconnect wallet when disconnect button clicked --- components/01-atoms/DisconnectWallet.tsx | 31 ++++++++++++++++++++ components/02-molecules/TheHeader.tsx | 6 ++-- components/02-molecules/TheSidebarHeader.tsx | 11 +++---- components/04-templates/Layout.tsx | 3 +- lib/client/contexts/SidebarContext.tsx.tsx | 30 +++++++++++++++++++ pages/index.tsx | 16 +++++----- 6 files changed, 79 insertions(+), 18 deletions(-) create mode 100644 components/01-atoms/DisconnectWallet.tsx create mode 100644 lib/client/contexts/SidebarContext.tsx.tsx diff --git a/components/01-atoms/DisconnectWallet.tsx b/components/01-atoms/DisconnectWallet.tsx new file mode 100644 index 00000000..f496df67 --- /dev/null +++ b/components/01-atoms/DisconnectWallet.tsx @@ -0,0 +1,31 @@ +import { PowerIcon } from "./icons/PowerIcon"; +import { useSidebar } from "@/lib/client/contexts/SidebarContext.tsx"; +import { useDisconnect } from "wagmi"; +import cc from "classcat" +import { useTheme } from "next-themes"; + +export const DisconnectWallet = () => { + const { disconnect } = useDisconnect(); + const { systemTheme, theme } = useTheme(); + const currentTheme = theme === "system" ? systemTheme : theme; + const isDark = currentTheme === "dark"; + const { toggleSidebar } = useSidebar(); + + const handleClick = () => { + toggleSidebar() + disconnect() + } + + return ( + + ); +}; diff --git a/components/02-molecules/TheHeader.tsx b/components/02-molecules/TheHeader.tsx index 93822e19..ce7e1712 100644 --- a/components/02-molecules/TheHeader.tsx +++ b/components/02-molecules/TheHeader.tsx @@ -10,6 +10,7 @@ import { } from "@/components/01-atoms"; import { useScreenSize } from "@/lib/client/hooks/useScreenSize"; import { useAuthenticatedUser } from "@/lib/client/hooks/useAuthenticatedUser"; +import { useSidebar } from "@/lib/client/contexts/SidebarContext.tsx"; import React, { useEffect, useState } from "react"; import { useTheme } from "next-themes"; import Link from "next/link"; @@ -21,11 +22,8 @@ export const TheHeader = () => { const [showFullNav, setShowFullNav] = useState( !isDesktop && !!authenticatedUserAddress?.address, ); - const [isSidebarOpen, setIsSidebarOpen] = useState(false); - const toggleSidebar = () => { - setIsSidebarOpen(!isSidebarOpen); - }; + const { toggleSidebar, isSidebarOpen } = useSidebar(); const { isWideScreen } = useScreenSize(); diff --git a/components/02-molecules/TheSidebarHeader.tsx b/components/02-molecules/TheSidebarHeader.tsx index 235a2b9f..30bfd454 100644 --- a/components/02-molecules/TheSidebarHeader.tsx +++ b/components/02-molecules/TheSidebarHeader.tsx @@ -1,5 +1,6 @@ import { CloseIcon } from "../01-atoms/icons/CloseIcon"; -import { PowerIcon } from "../01-atoms/icons/PowerIcon"; +import { DisconnectWallet } from "../01-atoms/DisconnectWallet"; +import { useSidebar } from "@/lib/client/contexts/SidebarContext.tsx"; import React from "react"; import cc from "classcat"; import { useTheme } from "next-themes"; @@ -8,10 +9,13 @@ export const TheSidebarHeader = () => { const { systemTheme, theme } = useTheme(); const currentTheme = theme === "system" ? systemTheme : theme; const isDark = currentTheme === "dark"; + const { toggleSidebar } = useSidebar(); + return (

-
- -

Disconnect

-
+
); diff --git a/components/04-templates/Layout.tsx b/components/04-templates/Layout.tsx index 98edf288..db81c87d 100644 --- a/components/04-templates/Layout.tsx +++ b/components/04-templates/Layout.tsx @@ -1,8 +1,9 @@ /* eslint-disable react-hooks/exhaustive-deps */ +import { SidebarProvider } from "@/lib/client/contexts/SidebarContext.tsx"; import { useAuthedAccess } from "@/lib/client/hooks/useAuthedAccess"; export const Layout = ({ children }: { children: React.ReactNode }) => { useAuthedAccess(); - return <>{children}; + return {children}; }; diff --git a/lib/client/contexts/SidebarContext.tsx.tsx b/lib/client/contexts/SidebarContext.tsx.tsx new file mode 100644 index 00000000..afc706c5 --- /dev/null +++ b/lib/client/contexts/SidebarContext.tsx.tsx @@ -0,0 +1,30 @@ +import React, { createContext, useContext, useState, ReactNode, useCallback } from 'react'; + +interface SidebarContextType { + isSidebarOpen: boolean; + toggleSidebar: () => void; +} + +const SidebarContext = createContext(undefined); + +export const SidebarProvider = ({ children }: { children: ReactNode }) => { + const [isSidebarOpen, setIsSidebarOpen] = useState(false); + + const toggleSidebar = useCallback(() => { + setIsSidebarOpen((prevState) => !prevState); + }, []); + + return ( + + {children} + + ); +}; + +export const useSidebar = () => { + const context = useContext(SidebarContext); + if (context === undefined) { + throw new Error('useSidebar must be used within a SidebarProvider'); + } + return context; +}; diff --git a/pages/index.tsx b/pages/index.tsx index f385c389..ed4a9a8e 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -5,14 +5,14 @@ import cc from "classcat"; export default function IndexPage() { return ( -
- - -
+
+ + +
); } From 0d5aa8e346757065c574002ecdc8561c3d8bcdce Mon Sep 17 00:00:00 2001 From: heronlancellot Date: Mon, 19 Feb 2024 18:39:53 -0300 Subject: [PATCH 83/94] fix: add pr 103 at a218835 --- .env.example | 8 +++--- README.md | 31 ++++++++++++++++++++++ components/01-atoms/ConnectWallet.tsx | 2 +- components/01-atoms/SearchBar.tsx | 3 +-- components/01-atoms/SelectDestinyChain.tsx | 3 +-- components/01-atoms/SwapModalButton.tsx | 3 +-- components/01-atoms/SwappingIcons.tsx | 11 +++----- components/01-atoms/icons/index.tsx | 20 -------------- components/01-atoms/index.ts | 20 ++++++++++++++ components/02-molecules/CardHome.tsx | 3 +-- components/02-molecules/NftCard.tsx | 1 + components/02-molecules/NftsList.tsx | 8 +++++- components/02-molecules/OfferSummary.tsx | 3 +-- components/02-molecules/SwapStation.tsx | 3 +-- components/02-molecules/TheHeader.tsx | 6 +++-- components/03-organisms/NftsShelf.tsx | 3 +-- components/04-templates/Layout.tsx | 1 + lib/client/blockchain-data.ts | 4 +-- lib/client/constants.ts | 6 +---- lib/client/hooks/useENSData.tsx | 9 +++++-- styles/global.css | 16 +++++++++++ 21 files changed, 106 insertions(+), 58 deletions(-) delete mode 100644 components/01-atoms/icons/index.tsx diff --git a/.env.example b/.env.example index 9a498d10..496cc963 100644 --- a/.env.example +++ b/.env.example @@ -1,16 +1,16 @@ -NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID= +NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID=50db9e195634356bb8ab0375a9f07607 NEXT_PUBLIC_ALCHEMY_SEPOLIA_HTTP= NEXT_PUBLIC_ALCHEMY_SEPOLIA_KEY= NEXT_PUBLIC_ALCHEMY_MUMBAI_HTTP= NEXT_PUBLIC_ALCHEMY_MUMBAI_KEY= NEXT_PUBLIC_ALCHEMY_ETHEREUM_HTTP= -#Subgraph endpoint production query +# Subgraph endpoint production query -#ENDPOINT_URL=https://gateway.testnet.thegraph.com/api/[api-key]/subgraphs/id/EynHJVht9r6xhaZEPCyLYLd4EqBq8msf4jTrw1Vwg8ZV +# ENDPOINT_URL=https://gateway.testnet.thegraph.com/api/[api-key]/subgraphs/id/EynHJVht9r6xhaZEPCyLYLd4EqBq8msf4jTrw1Vwg8ZV -#Subgraph endpoint production query +# Subgraph endpoint production query ENDPOINT_URL=https://api.studio.thegraph.com/query/57887/swaplace-subgraph-sepolia/version/latest diff --git a/README.md b/README.md index 45f1d403..ef85d40b 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,9 @@ ## Swaplace +This repository contains the core frontend for the Swaplace Protocol; The lightest Swap protocol in the market. + +## Setup + First, install the dependences: ```bash @@ -17,3 +21,30 @@ pnpm dev # or bun dev ``` + +### Environment Variables + +The project comes with a `.env.example` file. You should rename it to `.env` and fill the variables with your values. Most RPC providers offer free testnet nodes. You can use [Alchemy](https://www.alchemy.com/) or [Infura](https://infura.io/) to get a free node. + +``` +NEXT_PUBLIC_ALCHEMY_SEPOLIA_HTTP= +NEXT_PUBLIC_ALCHEMY_SEPOLIA_KEY= +NEXT_PUBLIC_ALCHEMY_MUMBAI_HTTP= +NEXT_PUBLIC_ALCHEMY_MUMBAI_KEY= +NEXT_PUBLIC_ALCHEMY_ETHEREUM_HTTP= +``` + +WARNING: The private keys used in the `.env` file are from hardhat accounts. They are not meant to be used in production. + +WARNING: The `NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID=` used in the `.env` file is public. They are not meant to be used in production. + +If you want use your own please create your Project ID in the [WalletConnect](https://cloud.walletconnect.com/) + +``` +NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID= + +``` + +## Contributing + +- To know more about how you can contribute [see our notion page](https://blockful.notion.site/Swaplace-Call-for-Contributors-6e4895d2a7264f679439ab2c124603fe). diff --git a/components/01-atoms/ConnectWallet.tsx b/components/01-atoms/ConnectWallet.tsx index 677e6485..77944f21 100644 --- a/components/01-atoms/ConnectWallet.tsx +++ b/components/01-atoms/ConnectWallet.tsx @@ -1,4 +1,4 @@ -import { WalletIcon } from "./icons"; +import { WalletIcon } from "@/components/01-atoms"; import { ConnectButton } from "@rainbow-me/rainbowkit"; import { useRouter } from "next/router"; diff --git a/components/01-atoms/SearchBar.tsx b/components/01-atoms/SearchBar.tsx index 758cd61d..6c6e4aa1 100644 --- a/components/01-atoms/SearchBar.tsx +++ b/components/01-atoms/SearchBar.tsx @@ -1,8 +1,7 @@ /* eslint-disable import/no-named-as-default */ /* eslint-disable react-hooks/exhaustive-deps */ /* eslint-disable import/no-named-as-default-member */ -import { MagnifyingGlassIcon } from "@/components/01-atoms/icons"; -import { SwapContext } from "@/components/01-atoms"; +import { MagnifyingGlassIcon, SwapContext } from "@/components/01-atoms"; import { useAuthenticatedUser } from "@/lib/client/hooks/useAuthenticatedUser"; import { useContext, useEffect, useState } from "react"; import { useTheme } from "next-themes"; diff --git a/components/01-atoms/SelectDestinyChain.tsx b/components/01-atoms/SelectDestinyChain.tsx index 11e48477..ebcfebcb 100644 --- a/components/01-atoms/SelectDestinyChain.tsx +++ b/components/01-atoms/SelectDestinyChain.tsx @@ -1,5 +1,4 @@ -import { SwapContext } from "@/components/01-atoms"; -import { EthereumIcon, PolygonIcon } from "@/components/01-atoms/icons"; +import { EthereumIcon, PolygonIcon, SwapContext } from "@/components/01-atoms"; import { ChainInfo, SupportedNetworks } from "@/lib/client/constants"; import { Fragment, useContext, useState } from "react"; import { Dialog, Transition } from "@headlessui/react"; diff --git a/components/01-atoms/SwapModalButton.tsx b/components/01-atoms/SwapModalButton.tsx index 2858cf59..44f47b29 100644 --- a/components/01-atoms/SwapModalButton.tsx +++ b/components/01-atoms/SwapModalButton.tsx @@ -1,7 +1,6 @@ /* eslint-disable @typescript-eslint/no-empty-function */ -import { SwapContext } from "."; import { LoadingIndicator } from "./LoadingIndicator"; -import { LeftIcon, RightIcon } from "@/components/01-atoms/icons"; +import { LeftIcon, RightIcon, SwapContext } from "@/components/01-atoms"; import React, { ButtonHTMLAttributes, useContext } from "react"; import { useTheme } from "next-themes"; import cc from "classcat"; diff --git a/components/01-atoms/SwappingIcons.tsx b/components/01-atoms/SwappingIcons.tsx index e0bb177c..cac7d3ce 100644 --- a/components/01-atoms/SwappingIcons.tsx +++ b/components/01-atoms/SwappingIcons.tsx @@ -3,8 +3,9 @@ import { OffersIcon, ChatIcon, NotificationsIcon, -} from "@/components/01-atoms/icons"; -import { Tooltip } from "@/components/01-atoms"; + Tooltip, +} from "@/components/01-atoms"; + import { useScreenSize } from "@/lib/client/hooks/useScreenSize"; import { useTheme } from "next-themes"; import { NextRouter, useRouter } from "next/router"; @@ -88,7 +89,6 @@ export const SwappingIcons = () => { return (
{isWideScreen ? ( -
{ ? "text-[#AABE13]" : "text-[#c1c3c2] group-hover:text-[#4F4F4F]", isDisabled && "disabled cursor-not-allowed", - ])} />
) : ( -
{ "flex-1 md:p-4 cursor-pointer hover:dark:bg-[#343635] hover:bg-[#eff3cf]", ])} onClick={() => { - handleClick(swappingTab); }} > @@ -150,7 +147,7 @@ export const SwappingIcons = () => {
)} - +
); })} diff --git a/components/01-atoms/icons/index.tsx b/components/01-atoms/icons/index.tsx deleted file mode 100644 index acb487cf..00000000 --- a/components/01-atoms/icons/index.tsx +++ /dev/null @@ -1,20 +0,0 @@ -export * from "./ChatIcon"; -export * from "./CheckIcon"; -export * from "./DangerIcon"; -export * from "./EthereumIcon"; -export * from "./LeftIcon"; -export * from "./MagnifyingGlassIcon"; -export * from "./NotificationsIcon"; -export * from "./OffersIcon"; -export * from "./PaperPlane"; -export * from "./PersonIcon"; -export * from "./PolygonIcon"; -export * from "./RightIcon"; -export * from "./SelectUserIcon"; -export * from "./SwapIcon"; -export * from "./SwaplaceIcon"; -export * from "./SwappingIcon"; -export * from "./XMarkIcon"; -export * from "./WalletIcon"; -export * from "./SunIcon"; -export * from "./MoonIcon"; diff --git a/components/01-atoms/index.ts b/components/01-atoms/index.ts index cf9e2787..9dd82add 100644 --- a/components/01-atoms/index.ts +++ b/components/01-atoms/index.ts @@ -15,3 +15,23 @@ export * from "./SwappingIcons"; export * from "./Tab"; export * from "./Tooltip"; export * from "./ENSAvatar"; +export * from "./icons/ChatIcon"; +export * from "./icons/CheckIcon"; +export * from "./icons/DangerIcon"; +export * from "./icons/EthereumIcon"; +export * from "./icons/LeftIcon"; +export * from "./icons/MagnifyingGlassIcon"; +export * from "./icons/NotificationsIcon"; +export * from "./icons/OffersIcon"; +export * from "./icons/PaperPlane"; +export * from "./icons/PersonIcon"; +export * from "./icons/PolygonIcon"; +export * from "./icons/RightIcon"; +export * from "./icons/SelectUserIcon"; +export * from "./icons/SwapIcon"; +export * from "./icons/SwaplaceIcon"; +export * from "./icons/SwappingIcon"; +export * from "./icons/XMarkIcon"; +export * from "./icons/WalletIcon"; +export * from "./icons/SunIcon"; +export * from "./icons/MoonIcon"; diff --git a/components/02-molecules/CardHome.tsx b/components/02-molecules/CardHome.tsx index 4985fabd..5f9f60e3 100644 --- a/components/02-molecules/CardHome.tsx +++ b/components/02-molecules/CardHome.tsx @@ -1,5 +1,4 @@ -import { ConnectWallet } from "@/components/01-atoms"; -import { SwaplaceIcon } from "@/components/01-atoms/icons"; +import { ConnectWallet, SwaplaceIcon } from "@/components/01-atoms"; import React from "react"; export const CardHome = () => { diff --git a/components/02-molecules/NftCard.tsx b/components/02-molecules/NftCard.tsx index f33fa3ab..e04247ff 100644 --- a/components/02-molecules/NftCard.tsx +++ b/components/02-molecules/NftCard.tsx @@ -1,3 +1,4 @@ +/* eslint-disable react-hooks/exhaustive-deps */ import { NFT } from "@/lib/client/constants"; import { SwapContext } from "@/components/01-atoms"; import { useAuthenticatedUser } from "@/lib/client/hooks/useAuthenticatedUser"; diff --git a/components/02-molecules/NftsList.tsx b/components/02-molecules/NftsList.tsx index 1c2e6e99..58b56174 100644 --- a/components/02-molecules/NftsList.tsx +++ b/components/02-molecules/NftsList.tsx @@ -1,7 +1,13 @@ -import { INftsList, NFT } from "@/lib/client/constants"; +import { NFT } from "@/lib/client/constants"; import { NftCard } from "@/components/02-molecules"; import { EmptyNftsCards } from "@/components/01-atoms"; +/* eslint-disable react/jsx-key */ +interface INftsList { + nftsList: NFT[]; + ownerAddress: string | null; +} + /** * * This component receives the data of multiple nfts and create its cards diff --git a/components/02-molecules/OfferSummary.tsx b/components/02-molecules/OfferSummary.tsx index 70596b56..bccf2d02 100644 --- a/components/02-molecules/OfferSummary.tsx +++ b/components/02-molecules/OfferSummary.tsx @@ -1,8 +1,7 @@ import { EthereumAddress } from "@/lib/shared/types"; import { useAuthenticatedUser } from "@/lib/client/hooks/useAuthenticatedUser"; -import { PersonIcon } from "@/components/01-atoms/icons"; import { NftCard } from "@/components/02-molecules"; -import { EmptyNftsCards, SwapContext } from "@/components/01-atoms"; +import { EmptyNftsCards, PersonIcon, SwapContext } from "@/components/01-atoms"; import { useEnsName } from "wagmi"; import { useContext } from "react"; diff --git a/components/02-molecules/SwapStation.tsx b/components/02-molecules/SwapStation.tsx index 6c6c7a64..4910fec0 100644 --- a/components/02-molecules/SwapStation.tsx +++ b/components/02-molecules/SwapStation.tsx @@ -1,5 +1,4 @@ -import { SwapContext, SwapExpireTime } from "@/components/01-atoms"; -import { PaperPlane } from "@/components/01-atoms/icons"; +import { PaperPlane, SwapContext, SwapExpireTime } from "@/components/01-atoms"; import { ConfirmSwapModal, OfferSummary } from "@/components/02-molecules"; import { useContext, useEffect, useState } from "react"; import cc from "classcat"; diff --git a/components/02-molecules/TheHeader.tsx b/components/02-molecules/TheHeader.tsx index f7f2d4ba..b58bbeb0 100644 --- a/components/02-molecules/TheHeader.tsx +++ b/components/02-molecules/TheHeader.tsx @@ -3,12 +3,14 @@ import { useAuthenticatedUser } from "@/lib/client/hooks/useAuthenticatedUser"; import { ConnectWallet, ENSAvatar, + MoonIcon, + SunIcon, + SwaplaceIcon, SwappingIcons, Tooltip, } from "@/components/01-atoms"; -import { MoonIcon, SunIcon, SwaplaceIcon } from "@/components/01-atoms/icons/"; -import { useTheme } from "next-themes"; import React, { useEffect, useState } from "react"; +import { useTheme } from "next-themes"; import Link from "next/link"; import cc from "classcat"; diff --git a/components/03-organisms/NftsShelf.tsx b/components/03-organisms/NftsShelf.tsx index 17aab793..fe71f0d7 100644 --- a/components/03-organisms/NftsShelf.tsx +++ b/components/03-organisms/NftsShelf.tsx @@ -3,8 +3,7 @@ import { NFT, ChainInfo, NFTsQueryStatus } from "@/lib/client/constants"; import { useAuthenticatedUser } from "@/lib/client/hooks/useAuthenticatedUser"; import { getNftsFrom } from "@/lib/client/blockchain-data"; import { EthereumAddress } from "@/lib/shared/types"; -import { SwapContext } from "@/components/01-atoms"; -import { SelectUserIcon } from "@/components/01-atoms/icons"; +import { SelectUserIcon, SwapContext } from "@/components/01-atoms"; import { NftsList } from "@/components/02-molecules"; import { useContext, useEffect, useState } from "react"; import { useTheme } from "next-themes"; diff --git a/components/04-templates/Layout.tsx b/components/04-templates/Layout.tsx index 10436a5a..98edf288 100644 --- a/components/04-templates/Layout.tsx +++ b/components/04-templates/Layout.tsx @@ -1,3 +1,4 @@ +/* eslint-disable react-hooks/exhaustive-deps */ import { useAuthedAccess } from "@/lib/client/hooks/useAuthedAccess"; export const Layout = ({ children }: { children: React.ReactNode }) => { diff --git a/lib/client/blockchain-data.ts b/lib/client/blockchain-data.ts index 6fce855d..3a48525b 100644 --- a/lib/client/blockchain-data.ts +++ b/lib/client/blockchain-data.ts @@ -1,7 +1,7 @@ -import { NFT, NFTsQueryStatus, getRpcHttpUrlForNetwork } from "./constants"; import { getTimestamp } from "./utils"; -import { hexToNumber } from "viem"; +import { NFT, NFTsQueryStatus, getRpcHttpUrlForNetwork } from "./constants"; import { Dispatch, SetStateAction } from "react"; +import { hexToNumber } from "viem"; export interface ICreateSwap { walletClient: any; diff --git a/lib/client/constants.ts b/lib/client/constants.ts index 1f7e3e46..a90473b0 100644 --- a/lib/client/constants.ts +++ b/lib/client/constants.ts @@ -1,3 +1,4 @@ +/* eslint-disable prefer-const */ export const ADDRESS_ZERO = "0x0000000000000000000000000000000000000000"; export const WIDE_SCREEN_SIZE = 1279; @@ -11,11 +12,6 @@ export interface NFT { contractMetadata?: Record; } -export interface INftsList { - nftsList: NFT[]; - ownerAddress: string | null; -} - export enum NFTsQueryStatus { EMPTY_QUERY = "EMPTY_QUERY", LOADING = "LOADING", diff --git a/lib/client/hooks/useENSData.tsx b/lib/client/hooks/useENSData.tsx index ec1fe53d..88bbb548 100644 --- a/lib/client/hooks/useENSData.tsx +++ b/lib/client/hooks/useENSData.tsx @@ -34,8 +34,13 @@ export const useEnsData = ({ ensAddress }: Props) => { address: ensAddress.address as `0x${string}`, }) .then((name) => { - setAvatarQueryStatus(ENSAvatarQueryStatus.SUCCESS); - setPrimaryName(name); + if (name) { + setAvatarQueryStatus(ENSAvatarQueryStatus.SUCCESS); + setPrimaryName(name); + } else { + setAvatarQueryStatus(ENSAvatarQueryStatus.ERROR); + setPrimaryName(null); + } }) .catch(() => { setAvatarQueryStatus(ENSAvatarQueryStatus.ERROR); diff --git a/styles/global.css b/styles/global.css index 6c059cbc..34f520da 100644 --- a/styles/global.css +++ b/styles/global.css @@ -15,6 +15,13 @@ input[type="search"]::-webkit-search-results-decoration { @tailwind utilities; @layer utilities { + .shadow-add-manually-card { + box-shadow: 0px 0px 12px 1px #00000066; + } + .shadow-add-manually-button { + box-shadow: 0px 0px 6px 1px rgba(0, 0, 0, 0.3); + } + .title-h1 { } @@ -64,7 +71,13 @@ input[type="search"]::-webkit-search-results-decoration { .p-medium-bold-2-dark { @apply font-onest font-medium text-[16px] leading-[20px] text-[#F6F6F6]; } + .p-medium-bold-2-dark-variant-black { + @apply font-onest font-medium text-[16px] leading-[20px] text-black; + } + .p-medium-bold-variant-black { + @apply font-onest font-medium text-[14px] leading-[16px] text-[#181A19]; + } .p-medium-bold { @apply font-onest font-medium text-[14px] leading-[16px] text-[#707572]; } @@ -79,6 +92,9 @@ input[type="search"]::-webkit-search-results-decoration { @apply font-onest font-medium text-[14px] leading-[20px] text-[#F6F6F6]; } + .p-small-variant-black { + @apply font-onest font-normal text-[14px] leading-[20px] text-[#181A19]; + } .p-small { @apply font-onest font-normal text-[14px] leading-[20px] text-[#707572]; } From cad5bbe19c6c2e77c0962dc8b8fcc9bf6652d2f2 Mon Sep 17 00:00:00 2001 From: heronlancellot Date: Mon, 19 Feb 2024 18:59:01 -0300 Subject: [PATCH 84/94] fix: add pr 103 at fc3e13f --- .eslintrc.json => .eslintrc | 0 .github/workflows/eslint.yml | 50 ++++++++++++++++++++++++++++ lib/client/hooks/useAuthedAccess.tsx | 1 + 3 files changed, 51 insertions(+) rename .eslintrc.json => .eslintrc (100%) create mode 100644 .github/workflows/eslint.yml diff --git a/.eslintrc.json b/.eslintrc similarity index 100% rename from .eslintrc.json rename to .eslintrc diff --git a/.github/workflows/eslint.yml b/.github/workflows/eslint.yml new file mode 100644 index 00000000..5fd22417 --- /dev/null +++ b/.github/workflows/eslint.yml @@ -0,0 +1,50 @@ +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. +# ESLint is a tool for identifying and reporting on patterns +# found in ECMAScript/JavaScript code. +# More details at https://github.com/eslint/eslint +# and https://eslint.org + +name: ESLint + +on: + push: + branches: ["main"] + pull_request: + # The branches below must be a subset of the branches above + branches: ["main"] + schedule: + - cron: "16 6 * * 3" + +jobs: + eslint: + name: Run eslint scanning + runs-on: ubuntu-latest + permissions: + contents: read + security-events: write + actions: read # only required for a private repository by github/codeql-action/upload-sarif to get the Action run status + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Install ESLint + run: | + npm install eslint@8.10.0 --legacy-peer-deps + npm install @microsoft/eslint-formatter-sarif@2.1.7 --legacy-peer-deps + + - name: Run ESLint + run: npx eslint . + --config .eslintrc.json + --ext .js,.jsx,.ts,.tsx + --format @microsoft/eslint-formatter-sarif + --output-file eslint-results.sarif + continue-on-error: true + + - name: Upload analysis results to GitHub + uses: github/codeql-action/upload-sarif@v3 + with: + sarif_file: eslint-results.sarif + wait-for-processing: true diff --git a/lib/client/hooks/useAuthedAccess.tsx b/lib/client/hooks/useAuthedAccess.tsx index 677e5fda..6138d402 100644 --- a/lib/client/hooks/useAuthedAccess.tsx +++ b/lib/client/hooks/useAuthedAccess.tsx @@ -1,3 +1,4 @@ +/* eslint-disable react-hooks/exhaustive-deps */ import { useAuthenticatedUser } from "./useAuthenticatedUser"; import { useRouter } from "next/router"; import { useEffect } from "react"; From 766aa6fbcda568ea008de37a01c778f16f09d3e8 Mon Sep 17 00:00:00 2001 From: heronlancellot Date: Mon, 19 Feb 2024 19:09:29 -0300 Subject: [PATCH 85/94] fix: add pr 103 at 986fd05 --- .github/workflows/eslint.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/eslint.yml b/.github/workflows/eslint.yml index 5fd22417..b2bb4788 100644 --- a/.github/workflows/eslint.yml +++ b/.github/workflows/eslint.yml @@ -37,7 +37,7 @@ jobs: - name: Run ESLint run: npx eslint . - --config .eslintrc.json + --config .eslintrc --ext .js,.jsx,.ts,.tsx --format @microsoft/eslint-formatter-sarif --output-file eslint-results.sarif From d447b83d9f74e23be6ad8dea324dce2aa0fabcd0 Mon Sep 17 00:00:00 2001 From: heronlancellot Date: Mon, 19 Feb 2024 19:35:33 -0300 Subject: [PATCH 86/94] fix: add pr 103 package.json --- components/01-atoms/SwapOfferDetails.tsx | 2 +- package-lock.json | 257 ++++++----------------- package.json | 6 +- 3 files changed, 67 insertions(+), 198 deletions(-) diff --git a/components/01-atoms/SwapOfferDetails.tsx b/components/01-atoms/SwapOfferDetails.tsx index 65614683..76be3e79 100644 --- a/components/01-atoms/SwapOfferDetails.tsx +++ b/components/01-atoms/SwapOfferDetails.tsx @@ -1,4 +1,4 @@ -import { CheckIcon, XMarkIcon } from "./icons"; +import { CheckIcon, XMarkIcon } from "@/components/01-atoms"; import React from "react"; export const SwapOfferDetails = () => ( diff --git a/package-lock.json b/package-lock.json index 1fe38235..a0e31293 100644 --- a/package-lock.json +++ b/package-lock.json @@ -38,8 +38,8 @@ "@typescript-eslint/parser": "^6.13.1", "autoprefixer": "^10.0.1", "dotenv": "^16.4.1", - "eslint": "^8", - "eslint-config-next": "14.0.3", + "eslint": "8.7.0", + "eslint-config-next": "13.4.19", "postcss": "^8", "tailwindcss": "^3.3.0", "typescript": "^5" @@ -114,39 +114,15 @@ "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz", "integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==" }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", - "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", - "dev": true, - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.4.1.tgz", + "integrity": "sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA==", "dev": true, "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.6.0", + "espree": "^9.4.0", "globals": "^13.19.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", @@ -161,15 +137,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/@eslint/js": { - "version": "8.55.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.55.0.tgz", - "integrity": "sha512-qQfo2mxH5yVom1kacMtZZJFVdW+E70mqHMJvVg6WTLo+VBuQJ4TojZlfWBjK0ve5BdEeNAVxOsl/nvNMpJOaJA==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, "node_modules/@ethereumjs/rlp": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@ethereumjs/rlp/-/rlp-4.0.1.tgz", @@ -956,36 +923,23 @@ } }, "node_modules/@humanwhocodes/config-array": { - "version": "0.11.13", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", - "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz", + "integrity": "sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==", "dev": true, "dependencies": { - "@humanwhocodes/object-schema": "^2.0.1", + "@humanwhocodes/object-schema": "^1.2.1", "debug": "^4.1.1", - "minimatch": "^3.0.5" + "minimatch": "^3.0.4" }, "engines": { "node": ">=10.10.0" } }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true, - "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", - "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", "dev": true }, "node_modules/@ioredis/commands": { @@ -1164,9 +1118,9 @@ "integrity": "sha512-7xRqh9nMvP5xrW4/+L0jgRRX+HoNRGnfJpD+5Wq6/13j3dsdzxO3BCXn7D3hMqsDb+vjZnJq+vI7+EtgrYZTeA==" }, "node_modules/@next/eslint-plugin-next": { - "version": "14.0.3", - "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-14.0.3.tgz", - "integrity": "sha512-j4K0n+DcmQYCVnSAM+UByTVfIHnYQy2ODozfQP+4RdwtRDfobrIvKq1K4Exb2koJ79HSSa7s6B2SA8T/1YR3RA==", + "version": "13.4.19", + "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-13.4.19.tgz", + "integrity": "sha512-N/O+zGb6wZQdwu6atMZHbR7T9Np5SUFUjZqCbj0sXm+MwQO35M8TazVB4otm87GkXYs2l6OPwARd3/PUWhZBVQ==", "dev": true, "dependencies": { "glob": "7.1.7" @@ -2518,12 +2472,6 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", - "dev": true - }, "node_modules/@vanilla-extract/css": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/@vanilla-extract/css/-/css-1.9.1.tgz", @@ -4542,49 +4490,46 @@ } }, "node_modules/eslint": { - "version": "8.55.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.55.0.tgz", - "integrity": "sha512-iyUUAM0PCKj5QpwGfmCAG9XXbZCWsqP/eWAWrG/W0umvjuLRBECwSFdt+rCntju0xEH7teIABPwXpahftIaTdA==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.55.0", - "@humanwhocodes/config-array": "^0.11.13", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", - "ajv": "^6.12.4", + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.7.0.tgz", + "integrity": "sha512-ifHYzkBGrzS2iDU7KjhCAVMGCvF6M3Xfs8X8b37cgrUlDt6bWRTpRh6T/gtSXv1HJ/BUGgmjvNvOEGu85Iif7w==", + "dev": true, + "dependencies": { + "@eslint/eslintrc": "^1.0.5", + "@humanwhocodes/config-array": "^0.9.2", + "ajv": "^6.10.0", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "debug": "^4.3.2", "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", + "eslint-scope": "^7.1.0", + "eslint-utils": "^3.0.0", + "eslint-visitor-keys": "^3.2.0", + "espree": "^9.3.0", + "esquery": "^1.4.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^6.0.1", + "globals": "^13.6.0", "ignore": "^5.2.0", + "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", + "minimatch": "^3.0.4", "natural-compare": "^1.4.0", - "optionator": "^0.9.3", + "optionator": "^0.9.1", + "regexpp": "^3.2.0", "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" + "strip-json-comments": "^3.1.0", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" }, "bin": { "eslint": "bin/eslint.js" @@ -4597,19 +4542,19 @@ } }, "node_modules/eslint-config-next": { - "version": "14.0.3", - "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-14.0.3.tgz", - "integrity": "sha512-IKPhpLdpSUyKofmsXUfrvBC49JMUTdeaD8ZIH4v9Vk0sC1X6URTuTJCLtA0Vwuj7V/CQh0oISuSTvNn5//Buew==", + "version": "13.4.19", + "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-13.4.19.tgz", + "integrity": "sha512-WE8367sqMnjhWHvR5OivmfwENRQ1ixfNE9hZwQqNCsd+iM3KnuMc1V8Pt6ytgjxjf23D+xbesADv9x3xaKfT3g==", "dev": true, "dependencies": { - "@next/eslint-plugin-next": "14.0.3", - "@rushstack/eslint-patch": "^1.3.3", + "@next/eslint-plugin-next": "13.4.19", + "@rushstack/eslint-patch": "^1.1.3", "@typescript-eslint/parser": "^5.4.2 || ^6.0.0", "eslint-import-resolver-node": "^0.3.6", "eslint-import-resolver-typescript": "^3.5.2", - "eslint-plugin-import": "^2.28.1", - "eslint-plugin-jsx-a11y": "^6.7.1", - "eslint-plugin-react": "^7.33.2", + "eslint-plugin-import": "^2.26.0", + "eslint-plugin-jsx-a11y": "^6.5.1", + "eslint-plugin-react": "^7.31.7", "eslint-plugin-react-hooks": "^4.5.0 || 5.0.0-canary-7118f5dd7-20230705" }, "peerDependencies": { @@ -5308,22 +5253,6 @@ "node": ">=0.10.0" } }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/flat-cache": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", @@ -5442,6 +5371,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==", + "dev": true + }, "node_modules/functions-have-names": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", @@ -5563,9 +5498,9 @@ "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==" }, "node_modules/globals": { - "version": "13.23.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", - "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", "dev": true, "dependencies": { "type-fest": "^0.20.2" @@ -5640,12 +5575,6 @@ "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==" }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true - }, "node_modules/h3": { "version": "1.10.1", "resolved": "https://registry.npmjs.org/h3/-/h3-1.10.1.tgz", @@ -6170,15 +6099,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/is-regex": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", @@ -6712,21 +6632,6 @@ "@types/trusted-types": "^2.0.2" } }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", @@ -7395,36 +7300,6 @@ "resolved": "https://registry.npmjs.org/outdent/-/outdent-0.8.0.tgz", "integrity": "sha512-KiOAIsdpUTcAXuykya5fnVVT+/5uS0Q1mrkRHcF89tpieSmY33O/tmc54CqwA+bfhbtEfZUNLHaPUiB9X3jt1A==" }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", @@ -9318,6 +9193,12 @@ "uuid": "dist/bin/uuid" } }, + "node_modules/v8-compile-cache": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.4.0.tgz", + "integrity": "sha512-ocyWc3bAHBB/guyqJQVI5o4BZkPhznPYUG2ea80Gond/BgNWpap8TOmLSeeQG7bnh2KMISxskdADG59j7zruhw==", + "dev": true + }, "node_modules/valtio": { "version": "1.11.2", "resolved": "https://registry.npmjs.org/valtio/-/valtio-1.11.2.tgz", @@ -10198,18 +10079,6 @@ "node": ">=8" } }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/zod": { "version": "3.22.4", "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.4.tgz", diff --git a/package.json b/package.json index 8bdc28d5..ab9f9c1d 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "dev": "next dev", "build": "next build", "start": "next start", - "lint": "next lint" + "lint": "next lint --config .eslintrc" }, "dependencies": { "@headlessui-float/react": "^0.13.0", @@ -39,8 +39,8 @@ "@typescript-eslint/parser": "^6.13.1", "autoprefixer": "^10.0.1", "dotenv": "^16.4.1", - "eslint": "^8", - "eslint-config-next": "14.0.3", + "eslint": "8.7.0", + "eslint-config-next": "13.4.19", "postcss": "^8", "tailwindcss": "^3.3.0", "typescript": "^5" From d4398396427e5e796ddd3f3058e303d8b115309c Mon Sep 17 00:00:00 2001 From: heronlancellot Date: Mon, 19 Feb 2024 21:09:08 -0300 Subject: [PATCH 87/94] feat: add padding search-bar --- components/01-atoms/SearchBar.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/01-atoms/SearchBar.tsx b/components/01-atoms/SearchBar.tsx index 6c6e4aa1..a50ab7dc 100644 --- a/components/01-atoms/SearchBar.tsx +++ b/components/01-atoms/SearchBar.tsx @@ -80,7 +80,7 @@ export const SearchBar = () => { }, [loadingENSaddress]); return ( -
+

Who are you swapping with today? From 4921fa811eeb3f31baada33735b2a339f2b334a0 Mon Sep 17 00:00:00 2001 From: heronlancellot Date: Mon, 19 Feb 2024 21:30:43 -0300 Subject: [PATCH 88/94] feat: add 0xneves CODEOWNER --- CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CODEOWNERS b/CODEOWNERS index b0269319..b0c0ffc7 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -1,3 +1,3 @@ # Default owners for everything in the repo -* @FrancoAguzzi @heronlancellot @eduramme +- @FrancoAguzzi @heronlancellot @eduramme @0xneves From b88e778cb1d85459b303361c0ab1fcfe9749336e Mon Sep 17 00:00:00 2001 From: eduramme Date: Tue, 20 Feb 2024 13:11:35 -0300 Subject: [PATCH 89/94] remove 'connect wallet' text --- components/02-molecules/TheHeader.tsx | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/components/02-molecules/TheHeader.tsx b/components/02-molecules/TheHeader.tsx index 28e6b494..7e966132 100644 --- a/components/02-molecules/TheHeader.tsx +++ b/components/02-molecules/TheHeader.tsx @@ -17,20 +17,9 @@ import Link from "next/link"; import cc from "classcat"; export const TheHeader = () => { - const { isDesktop } = useScreenSize(); const { authenticatedUserAddress } = useAuthenticatedUser(); - const [showFullNav, setShowFullNav] = useState( - !isDesktop && !!authenticatedUserAddress?.address, - ); - const { toggleSidebar, isSidebarOpen } = useSidebar(); - const { isWideScreen } = useScreenSize(); - - useEffect(() => { - setShowFullNav(!isDesktop); - }, [isDesktop]); - const { systemTheme, theme, setTheme } = useTheme(); const [mounted, setMounted] = useState(false); @@ -52,9 +41,6 @@ export const TheHeader = () => { fill={cc([theme == "dark" ? "#DDF23D" : "#4F4F4F"])} /> -
- -

From 454b9cd21ad1445336c44f191e227ad440a28031 Mon Sep 17 00:00:00 2001 From: eduramme Date: Tue, 20 Feb 2024 13:14:51 -0300 Subject: [PATCH 90/94] resolve requested changes --- components/01-atoms/index.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/components/01-atoms/index.ts b/components/01-atoms/index.ts index fb04dee6..583c326f 100644 --- a/components/01-atoms/index.ts +++ b/components/01-atoms/index.ts @@ -21,14 +21,11 @@ export * from "./icons/DangerIcon"; export * from "./icons/EthereumIcon"; export * from "./icons/ErrorIcon"; export * from "./icons/LeftIcon"; -export * from "./icons/MagnifyingGlassIcon"; export * from "./icons/NotificationsIcon"; export * from "./icons/OffersIcon"; -export * from "./icons/PaperPlane"; export * from "./icons/PersonIcon"; export * from "./icons/PolygonIcon"; export * from "./icons/RightIcon"; -export * from "./icons/SelectUserIcon"; export * from "./icons/SwapIcon"; export * from "./icons/SwaplaceIcon"; export * from "./icons/SwappingIcon"; From 9ae9be24c66e9e75905a7772d25fc9df132098c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20Jos=C3=A9?= Date: Tue, 20 Feb 2024 15:06:31 -0300 Subject: [PATCH 91/94] feat: add a active status to StatusOffers atom --- components/01-atoms/StatusOffers.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/01-atoms/StatusOffers.tsx b/components/01-atoms/StatusOffers.tsx index a5930aa1..8d741e85 100644 --- a/components/01-atoms/StatusOffers.tsx +++ b/components/01-atoms/StatusOffers.tsx @@ -43,7 +43,7 @@ export const StatusOffers = () => { return (
From 54d2f25347e4a2485d51b6ea9fab317bfc3fd727 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20Jos=C3=A9?= Date: Tue, 20 Feb 2024 23:01:55 -0300 Subject: [PATCH 92/94] refactor: component design refactor --- components/01-atoms/StatusOffers.tsx | 40 +++++++++++++++++++--------- 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/components/01-atoms/StatusOffers.tsx b/components/01-atoms/StatusOffers.tsx index 8d741e85..6db7d7ff 100644 --- a/components/01-atoms/StatusOffers.tsx +++ b/components/01-atoms/StatusOffers.tsx @@ -1,9 +1,16 @@ +import { useState } from "react"; +import cc from "classcat"; + export const StatusOffers = () => { + + const [OfferIsActive, setOfferIsActive] = useState(0); + enum FilterOptions { ALL_OFFERS = "All offers", - ACTIVE = "Active", + CREATED = "Created", + RECEIVED = "Received", ACCEPTED = "Accepted", - REJECTED = "Rejected", + CANCELED = "Canceled", EXPIRED = "Expired", } @@ -17,20 +24,24 @@ export const StatusOffers = () => { id: 1, name: FilterOptions.ALL_OFFERS, }, - [FilterOptions.ACTIVE]: { + [FilterOptions.CREATED]: { id: 2, - name: FilterOptions.ACTIVE, + name: FilterOptions.CREATED, }, - [FilterOptions.ACCEPTED]: { + [FilterOptions.RECEIVED]: { id: 3, - name: FilterOptions.ACCEPTED, + name: FilterOptions.RECEIVED, }, - [FilterOptions.REJECTED]: { + [FilterOptions.ACCEPTED]: { id: 4, - name: FilterOptions.REJECTED, + name: FilterOptions.ACCEPTED, }, - [FilterOptions.EXPIRED]: { + [FilterOptions.CANCELED]: { id: 5, + name: FilterOptions.CANCELED, + }, + [FilterOptions.EXPIRED]: { + id: 6, name: FilterOptions.EXPIRED, }, }; @@ -43,13 +54,16 @@ export const StatusOffers = () => { return (
setOfferIsActive(index)} > -
+
{name}
-
+
{id}
From df0ab0933ad19cebf0b3d991a479cfcc655d2a00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20Jos=C3=A9?= Date: Mon, 26 Feb 2024 03:04:59 -0300 Subject: [PATCH 93/94] refactor: add address search function just by typing it --- components/01-atoms/SearchBar.tsx | 105 ++++++++++++++++-------------- 1 file changed, 55 insertions(+), 50 deletions(-) diff --git a/components/01-atoms/SearchBar.tsx b/components/01-atoms/SearchBar.tsx index a50ab7dc..ce645981 100644 --- a/components/01-atoms/SearchBar.tsx +++ b/components/01-atoms/SearchBar.tsx @@ -3,34 +3,30 @@ /* eslint-disable import/no-named-as-default-member */ import { MagnifyingGlassIcon, SwapContext } from "@/components/01-atoms"; import { useAuthenticatedUser } from "@/lib/client/hooks/useAuthenticatedUser"; -import { useContext, useEffect, useState } from "react"; +import { SearchUserDelay } from "@/lib/client/constants"; +import { useContext, useEffect } from "react"; import { useTheme } from "next-themes"; import { ENS } from "web3-eth-ens"; import cc from "classcat"; import Web3 from "web3"; export const SearchBar = () => { - const { setInputAddress, inputAddress, validateAddressToSwap } = + const { setInputAddress, inputAddress, validateAddressToSwap, setUserJustValidatedInput } = useContext(SwapContext); const { authenticatedUserAddress } = useAuthenticatedUser(); - const [validateAfterENSaddressLoads, setValidateAfterENSaddressLoads] = - useState(false); - const validateInput = () => { - if (authenticatedUserAddress) { - if (loadingENSaddress) { - setValidateAfterENSaddressLoads(true); - } else { - validateAddressToSwap(authenticatedUserAddress, ensNameAddress); - } - } - }; const { theme } = useTheme(); - const [ensNameAddress, setEnsNameAddress] = useState(""); - const [loadingENSaddress, setLoadingENSaddress] = useState(false); - useEffect(() => { + // eslint-disable-next-line @typescript-eslint/no-unused-vars, unused-imports/no-unused-vars + + const validateUser = (ensNameAddress: string) => { + if (!authenticatedUserAddress) return + + validateAddressToSwap(authenticatedUserAddress, ensNameAddress); + } + + const getUserAddress = async () => { if (inputAddress) { if (!process.env.NEXT_PUBLIC_ALCHEMY_ETHEREUM_HTTP) { throw new Error( @@ -44,40 +40,45 @@ export const SearchBar = () => { const ens = new ENS(undefined, provider); - ens - .getOwner( - inputAddress.toLowerCase().includes(".") - ? inputAddress.toLowerCase().includes(".eth") - ? inputAddress.split(".")[1].length >= 3 - ? inputAddress - : `${inputAddress.split(".")[0]}.eth` - : inputAddress.split(".")[1].length >= 3 + const formattedAddress = + inputAddress.toLowerCase().includes(".") + ? inputAddress.toLowerCase().includes(".eth") + ? inputAddress.split(".")[1].length >= 3 ? inputAddress : `${inputAddress.split(".")[0]}.eth` - : `${inputAddress}.eth`, - ) - .then((address: unknown) => { - if (typeof address == "string") { - setEnsNameAddress(address); - setLoadingENSaddress(false); - } else { - setEnsNameAddress(""); - setLoadingENSaddress(false); - } - }) - .catch(() => { - setEnsNameAddress(""); - setLoadingENSaddress(false); - }); + : inputAddress.split(".")[1].length >= 3 + ? inputAddress + : `${inputAddress.split(".")[0]}.eth` + : `${inputAddress}.eth`; + + try { + const address: unknown = await ens.getOwner(formattedAddress); + + if (typeof address !== "string") return + validateUser(address); + + } + catch (e) { + console.log(e); + } + finally { + setUserJustValidatedInput(true); + } } - }, [inputAddress]); + } useEffect(() => { - if (!loadingENSaddress && validateAfterENSaddressLoads) { - validateInput(); - setValidateAfterENSaddressLoads(false); - } - }, [loadingENSaddress]); + const requestDelay = setTimeout(() => { + + setUserJustValidatedInput(false); + + getUserAddress(); + + }, SearchUserDelay); + + return () => clearTimeout(requestDelay); + + }, [inputAddress]); return (
@@ -92,15 +93,14 @@ export const SearchBar = () => { name="search" type="search" className={cc([ - "dark:bg-[#212322] w-full h-11 px-4 py-3 border-2 border-gray-100 dark:border-[#353836] focus:ring-0 focus:ring-transparent focus:outline-none focus-visible:border-gray-300 rounded-xl placeholder:p-small dark:placeholder:p-small ", + "dark:bg-[#212322] w-full h-11 px-4 py-3 border-2 border-gray-100 dark:border-[#353836] focus:ring-0 focus:ring-transparent focus:outline-none focus-visible:border-gray-300 rounded-xl placeholder:p-small dark:placeholder:p-small ", ])} placeholder="Search username, address or ENS" - onChange={(e) => setInputAddress(e.target.value)} + onChange={({ target }) => setInputAddress(target.value)} />
@@ -127,3 +127,8 @@ export const SearchBar = () => {
); }; + + + +//primeira busca após conectar wallet: Se for um ENS, irá (as vezes) não aparecer o inventário. +//problema: TheirItems não mostra o inventário da mesma busca duas vezes consecutivas. From 8ee93642ba23d7143d455dcaebf6a861f50d20a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20Jos=C3=A9?= Date: Mon, 26 Feb 2024 03:05:30 -0300 Subject: [PATCH 94/94] refactor: add address search function just by typing it --- components/01-atoms/SearchBar.tsx | 52 ++++++++++--------------------- 1 file changed, 16 insertions(+), 36 deletions(-) diff --git a/components/01-atoms/SearchBar.tsx b/components/01-atoms/SearchBar.tsx index ce645981..ffdef78a 100644 --- a/components/01-atoms/SearchBar.tsx +++ b/components/01-atoms/SearchBar.tsx @@ -3,7 +3,6 @@ /* eslint-disable import/no-named-as-default-member */ import { MagnifyingGlassIcon, SwapContext } from "@/components/01-atoms"; import { useAuthenticatedUser } from "@/lib/client/hooks/useAuthenticatedUser"; -import { SearchUserDelay } from "@/lib/client/constants"; import { useContext, useEffect } from "react"; import { useTheme } from "next-themes"; import { ENS } from "web3-eth-ens"; @@ -20,7 +19,7 @@ export const SearchBar = () => { // eslint-disable-next-line @typescript-eslint/no-unused-vars, unused-imports/no-unused-vars - const validateUser = (ensNameAddress: string) => { + const validateUser = (ensNameAddress: string | null) => { if (!authenticatedUserAddress) return validateAddressToSwap(authenticatedUserAddress, ensNameAddress); @@ -68,14 +67,14 @@ export const SearchBar = () => { } useEffect(() => { + const requestDelay = setTimeout(() => { setUserJustValidatedInput(false); getUserAddress(); - }, SearchUserDelay); - + }, 2000); return () => clearTimeout(requestDelay); }, [inputAddress]); @@ -87,48 +86,29 @@ export const SearchBar = () => { Who are you swapping with today?
-
+
+
+ +
setInputAddress(target.value)} /> -
-
- -
-
); }; - - - -//primeira busca após conectar wallet: Se for um ENS, irá (as vezes) não aparecer o inventário. -//problema: TheirItems não mostra o inventário da mesma busca duas vezes consecutivas.