From e7143d4920958634260626283812c334b2155a5b Mon Sep 17 00:00:00 2001 From: "Petros G. Sideris" Date: Fri, 7 Nov 2025 23:10:33 +0000 Subject: [PATCH 1/5] Add screen to transfer tokens and minor UX --- src/app.tsx | 5 + src/components/Header.tsx | 5 +- src/components/abi/AbiFunctionsAccordion.tsx | 6 +- src/design-system/components/SFSymbol.tsx | 2 + src/design-system/tokens.ts | 1 + src/screens/account-details.tsx | 222 +++++++++++------ src/screens/block-details.tsx | 7 +- src/screens/index.tsx | 6 +- src/screens/token-transfer.tsx | 237 +++++++++++++++++++ 9 files changed, 405 insertions(+), 86 deletions(-) create mode 100644 src/screens/token-transfer.tsx diff --git a/src/app.tsx b/src/app.tsx index fce28ee..71da54a 100644 --- a/src/app.tsx +++ b/src/app.tsx @@ -50,6 +50,7 @@ import OnboardingRun from './screens/onboarding/run' import OnboardingStart from './screens/onboarding/start' import Session from './screens/session' import Settings from './screens/settings' +import TokenTransfer from './screens/token-transfer' import TransactionDetails from './screens/transaction-details' export function init({ type = 'standalone' }: { type?: AppMeta['type'] } = {}) { @@ -73,6 +74,10 @@ export function init({ type = 'standalone' }: { type?: AppMeta['type'] } = {}) { path: 'account/:address', element: , }, + { + path: 'transfer/:accountAddress/:tokenAddress?', + element: , + }, { path: 'block-config', element: , diff --git a/src/components/Header.tsx b/src/components/Header.tsx index ef6afd4..5b6a0b5 100644 --- a/src/components/Header.tsx +++ b/src/components/Header.tsx @@ -431,10 +431,9 @@ function BaseFee() { ) if (!block) return null return ( - + - {intl.format(Number(formatGwei(block.baseFeePerGas!)))}{' '} - gwei + {intl.format(Number(formatGwei(block.baseFeePerGas!)))} ) diff --git a/src/components/abi/AbiFunctionsAccordion.tsx b/src/components/abi/AbiFunctionsAccordion.tsx index ffa8a28..412d40c 100644 --- a/src/components/abi/AbiFunctionsAccordion.tsx +++ b/src/components/abi/AbiFunctionsAccordion.tsx @@ -213,7 +213,7 @@ export function AbiFunctionContent({ + } + /> + + + + {/* Action Buttons */} + + + + + + + + + ) +} From ab28477d69bcec20dfcd5c39d057d48ce041c110 Mon Sep 17 00:00:00 2001 From: "Petros G. Sideris" Date: Fri, 7 Nov 2025 23:12:04 +0000 Subject: [PATCH 2/5] Version bump --- package.json | 2 +- src/screens/account-details.tsx | 18 +++++++++++------- src/screens/token-transfer.tsx | 5 +++-- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index 069ad93..c70278e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "devwallet", - "version": "0.1.0", + "version": "0.2.0", "private": true, "extension": { "name": "DW: DevWallet", diff --git a/src/screens/account-details.tsx b/src/screens/account-details.tsx index 1a875d5..9ca18c7 100644 --- a/src/screens/account-details.tsx +++ b/src/screens/account-details.tsx @@ -16,7 +16,11 @@ import * as Form from '~/components/form' import { Spinner } from '~/components/svgs' import { truncate } from '~/utils' -function formatBalance(balance: bigint, decimals: number, maxDecimals = 5): string { +function formatBalance( + balance: bigint, + decimals: number, + maxDecimals = 5, +): string { const formatted = formatUnits(balance, decimals) const [whole, decimal] = formatted.split('.') if (!decimal) return whole @@ -233,11 +237,7 @@ function NativeTokenRow({ accountAddress }: { accountAddress: Address }) { {typeof balance === 'bigint' && ( - + {formatBalance(balance, decimals)} )} @@ -322,7 +322,11 @@ function TokenRow({ borderColor="surface/invert@0.2" padding="2px" > - + {symbol || '???'} diff --git a/src/screens/token-transfer.tsx b/src/screens/token-transfer.tsx index 3469459..4244781 100644 --- a/src/screens/token-transfer.tsx +++ b/src/screens/token-transfer.tsx @@ -13,6 +13,7 @@ import { import { Container } from '~/components' import * as Form from '~/components/form' import { Spinner } from '~/components/svgs' +import { erc20Abi } from '~/constants/abi' import { Box, Button, @@ -28,7 +29,6 @@ import { useClient } from '~/hooks/useClient' import { useErc20Balance } from '~/hooks/useErc20Balance' import { useErc20Metadata } from '~/hooks/useErc20Metadata' import { useWriteContract } from '~/hooks/useWriteContract' -import { erc20Abi } from '~/constants/abi' type TransferFormData = { recipient: string @@ -176,7 +176,8 @@ export default function TokenTransfer() { register={register('amount', { required: 'Amount is required', validate: (value) => { - if (!value || value === '0') return 'Amount must be greater than 0' + if (!value || value === '0') + return 'Amount must be greater than 0' try { const amount = parseUnits(value, decimals) if (balance && amount > balance) { From c1c4a2f28f15dcc9f04d7c0f2bf49aebcd26f015 Mon Sep 17 00:00:00 2001 From: "Petros G. Sideris" Date: Fri, 7 Nov 2025 23:51:07 +0000 Subject: [PATCH 3/5] account details send does not delete anymore --- bun.lockb | Bin 381736 -> 383106 bytes package.json | 8 +- src/screens/account-details.tsx | 676 +++++++++++++------------------- src/screens/index.tsx | 2 +- 4 files changed, 285 insertions(+), 401 deletions(-) diff --git a/bun.lockb b/bun.lockb index b952b8c8ffb7ab2ccb91543588612463130d1630..f8de0c7852ea746dbef20a2b10b626f52bf98f02 100755 GIT binary patch delta 61303 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

XmfvQiQRy&-kfhz|;{Ih*Z%^R zUf3tQhzl*qIM6kwn3Cn|#t+OZR_#=Q#QliMBW_57IW&sB9P#>2>%6ZEGzxVpdaC&< zY#RMi=$>NhW_{QsSS5D!_CSJ&!Rs1nz|rq zbVWm|lb4oup;)sK6Qw#qK{B`oT~n?z=!q0lqt!dsmhJz#;98(D7l~}L4&AGHZ}X9x z%L^oHuc=t#hU`N_{Os7=zPCzFTKAO3X;YFvz0oVJnJFu4E?GZy+Ipox!}g2Xf`-iu z|3lMEEA+*=y|{#C9sZ-1W;@s>-&6}{;(6c7Q^#nR(Es|Jhp~P>*=_xa7PpsPGnZ4W z*be3?`z+3^eo-N_Sirn^-(SdSf~?iB8_vQrXR$pgJ>T#(oFSazp5Ng9XO`yq3${O~>(=hkx)QFoc=6 zjTNufEwIx!Mb>|ghWUwtOSe^-x#Y3nj*6bk6nK85+BBCKFE~7u(U+jENDL!)H}(2F zt%7~$-$oHOUD%Ub`OTVA8FRm5)?AIAr?q!{7Rg@wo-ww!->-NsJvDPD>b(2noxP?0 zy^Ig(|7IwN8=lf4qScDqY3%t$K{hf;NMzuqKFTTYziNuR&DxzOaw0bNo@zr}+p>GA z|A%zqmpqr%V4wSn-wEa2)jj39Kyz1Lf2j2>vGu+YDd)aAv7B97+#*f09lfvomucmS z)MeB2{e3k!18cgb+OOaw`@jNC<0sk=&ezIU47NDs8{4ek29BLlynZML4o3NdENmz* zEg-Y9`6`d-q1Dio;zqiaS$C!0JURL`ZLL0%N=UkoS-J0y+eP`%g5Cx}mhSl~Txl^O zj-Lx1HvhQG__P@LXaXM#PQsXjOR{(yR-Px)hW-y#$@z4DlzE@+@%e=lCmvnZ zsd9re$xY-Y1NOF8vc zbyM9IXcZmL|J5DN(j8BAgZ=+(eW&&ot9r0NYvssS#VzE}-_h6U3;)&EL3|TRZCOaC zwY93$wVIoAU|qg3qrzA6=$KVKLS#Q?wd&iU`!Dw!^eFfnIXY#wlJlM?k%BFb40L1a z>7;y?U`$d)NA*nw{h7nqq}Lo)V-&>A8CUdzWS_Q2+cTD})$(^F>d$LaGqXx^eWi$1 zU%XeC-EwF`)?94CmpMlM-B%|Uvov=ps&ZwJI7%pyj2d`6eX^n1J}RniEkTi-h7yM6 zFp%UR%)RXOm>Ox#<>bUXDSxrVY#Mc9$rIDi&rP1BZeLu&s_)YV94|h|+I}l9{TwF- zJ4&dknT+m}Xt#Gsed?M&QM%1f%oQbI$Ix3DGE zdb!_NQe9li2guf!vg+lZxovXAhrLUj(f9dsIuStY#$}PR={G9Y@}J2UWMnW~l5#$~ znLdI;KL)eD^D{cITz$sp3!FnRM%rnpAKy93=WnTmM3&|CcTMl~z%6l`A(4$txQkl6+^`3H zr@Izl+Fi^OQxYxHteoXqAIgqmms6=LFaoofML35IqNZ6ZNYRX=4y;DOQOV~=h^nxX zmyFMhSKFa7YIwo;b=Ul#9#9Lc4XqpXP>owdd*j(-*78x2O>4B^ zfrYtuV~T%13+4WwS%d_IykI&B2$JbUGPODS^@&6ED6C75iK^j}3%b-pd9BmRl=#fc za0uUesnB(FE{|~G@T)8PjV_hc^7X90Mpja{(0o#W5XWb_94j(4Z38y+Oa`IRm96?l zV&ggYkb{4>;jAlw*B7$J?}fyJJ~hY~H|63p8%3SsPi-4wv6N;-CM= zYTHIW(``|AHfkTI44rB$ZjMab_VCko?N^WIUQVok9yxJ7IWyH0AsIZK+)3tE;zKnDU=5#n0Rok+iid z_cDY0{C%gr?UH6V4Nk~XzMHhz`VUxCipknuf3Hu*nv%ILca0YjE@$UYeUS0hzKYy? zA-Cjyd+q4)2L5sKTO|DZ_518Yo3t%OtfAR&?$F{T{BDmn*RDErbM{fGXEj&;q_F0r z%KeYez586!T+~M=Sr?XD;*buz%%}d#+|;TV%A2=pMYEUwpq2hct^AF6aYvntD*ua` Rv+D7aRx53D}6vQnEG9@+BQZIfU5SoO2y3~?1J@;|aF z{FJO3-_GLp-j4J_r>wmeMQN!h*$ulYN*m|}FGXn$t%Np%PVA;A4WVhN@p03T_bmLz z@E?ITf%bvk3%%N1Q8Z{f_$==uBpqS#-yYo4g5xkPkumBGcA5@%(S?a>AxX0&*BrQQBbzdqtK?%&ju(;1L*ru9xM?29_Xb2(?1`eFR0f! zYhsY;o&{zjo`=t>hYU0|B^ous$5DJjTw+{8TxuG`;BO%vi|-BP;TsGx%XtFIa!x>5 zjYKFrW!hjf{W$n;ijtK*Gl}P_C}nmt!)s7hC7LD@UshM4hZq3l%w&VrXhU7@K^ zR=|IVnSYw(4ThTe9ej37#ylRc0=%J;rDR`026TJ&=g`*BQOL+)B8ytS5;W zjPFe|(;b$&08@YiB0gqbBI}t9pA8!(bv%@-!StAzWbe3CWhe4+rWHZifD2*_KP&r7 z1eoyzlr6sw3D_g)(EFjYFd(85;+3eBnaNQpsWBKiGvkw{DeuoT^To|fOiDpsAfsSL zM#ZNpjvkv1&K{f*mpI*fZnBbsVMl+aq5ZKQdB-P3N2Q^f@tDME%FJ12f-%U*GrS6) z6-KPsUJW~Ey*OKzA0L&L7BgKLjBGs7nAEvxai~X3>YTYTDH+PG z1hbf!)Z~;H)OQLRxEa!Ap!wJ!QPD{$Y)L=l=lO3;GWqnR=(Lo$#F!rPJR*|K@?V3Z zqx8=jc5q)f#~k$2p{XsJRQ`(L_rgGx=js9w<2`aXPRv zH#sUT7Me2EJYlnmv6_Ve@Id}h9;gSDEzlmyG1nZ*GjUu_qGO}t(XGmz*QiiTDpuUF zI=tX(R`_QqTjX}?KeY<7m@uwvv#ZQY$jY*A->cQ3QLvZF#jY*h?)5Byi2EYDeW7jOlaB~c^ z=`qvh&O}uckdGh7aB~d546Fc*+L33Tdxnp1BGYYz?}}rrg0d}RQlq2dqo&71$H&c$ zL%d_@PmW7WV*2hYjmgn4y8r=ZxVchad{5`B3#-g?_!XFgWXEcG4du?Gm!h-)Zvn1C zd1j%Fln0!J)rX&`S@R5atO^AM=HU4j^OXnQu-2@w^?9?x*Weo$ z{gfCC+|)E>?p$*ePI$pQgW*z>Q#tz-WsdBj0PuTI;6qRr+)XM*cZ@gIT{rm6z~fR= z)3C2hXaJw1Cp9%Tc{a*9v%xI?1XQ~p5i!xx-m_AtB_5R#4D*09W760VO1};IP}j~` z?k}3hi-xj=J3-lC4t@hC#s+!yB{SV0@Y!Ie6 z5gZ?rni@4fwKos{q0FCv^$DLW#ecJTKMGb_f6WOPz;M&}~4TwDrb&=ATQ#Is?WY%zQ665>6$J&Q?6 zNlL-Sz`E7U@C_n326gxxyFWlXLO+xRyt~beFNLze188osWiMLwt?oJbqHDcWP{0 zf|9q>Y>1}2OzxPHJK;A*x|=Iab*v-n!MOm(rADQsL}e(B5%4L>It=%1w~ z{}js3+5_dHETm@0_zBV<0A=}|psk@Tpcq9Bvy+oj)1omwDvs)1?`@m)?7L=XE`l~g zx&$a2ZKC8M((f(fJ4)VI@~g+ph3-2j^Ho4wLibAkGL+@6l<^Cp96Ym3|H14r2($nQ zf-+%uC|683GeNdR#{c?`d4Mn8(XZXx$Fk=`y;qAKS&oY+#<;OyC#R&at(6%cnum#i za`Ir8Fh4dbO_>*$W^`&wQhYr2cgn$!&E~zcTV4cjg?x_gSqh)cc}F*8Wyd0d{S^Z3 z0Cn_N7x;Di%^7|t#Q%5wcm5;uK>tlY%5KbJKbmKVVVA^}I3{)4+_?DZilZYO9pvZ` zM|(Tk)zRLLj(2ppqk|nC>*zq)ac2L7;fx#|;}}7Xk>coiN5?uwnqy=+Mv`Mhpkuqb zb!wH_vS!<8_I@$MQRSz1AaV|Ju^aTA1HgSEz}KKAIbrF@jG*zeJ=GF zl;doN)OAn{;H>OiGmt%3>U1cVy%&Em=XV5rE+39v^D%sq3qmoQqNyCkNO3aN6WC7>1JV<8I3-2 zGRx1(4n}~D>I3CzTt)^q(#)7dUgs4y_Cv^!3C__}fM)0nT>@pk7%203*Hewv%W=T> z;FCKJ+)~CnDyG11$&0chgCn6MK{yI#yIsb?Ijld{R72M_P?aw56XJQ}joTMI2jM58 zp=$Ih?`C4)ABWE~&qaE+d(6D3c&00BWb)zQ?XnQz=vYUSJ8p$1G**o>^@nnPb%e61 zWz%J=@VU@Ay2R16cXo}VOTKnhjTUosC3hWJ>`O<1j;42vi4D!n13JcpW8~dA(j5N3 z8fpKEV+4m7D~V$WZ*wtg=s1HrYwj2W`_UEdsQB;hW|L2DrKfn=mMEwdi!0Y+HQ8*)uiKv)_UlGp1XPu$f>6W>1s;fT^9zGwA7n? z+|&A`m!gE}l`+9um#&I34%tGDRymhcSRY66c*hlC%~$DD@s4Ta%iyiVT8u%9zO(IS0OY&4;vk9 z{ScwC;^gO+W@4(p+EeS*Ls1??URQn7$^b0|-avTHx;i$%x*ML|NUL8M-P5)61Bw!i zNK7^3W6?WA^|i!3pf8wacYOzu%qioPCVEgvU$wrjMTh9=)7FG6322^i2T)nlC(G zcozNK&;V^Ay#7YY9bp05es~y4*;akdm;mi2yb-nDaEul9ixFpC4lh`D2|x=YG|H%6 zhraspIJ*|rS5d&S6&}ti;Puig1_x{3AjHD!>*s<3w9cpltKqEs^zW-<39`Xs`Odm4 zYFPx2?Q7QZGCZ@E=OzVMeEjqV@pdiU&xB6wJZ(2TX28h8iClp<8lIv@6$Mzv_tU#3 z*tOLUn@OBFZZr=Rh?Yf$k;Q?|aQblQSf1>!4^6bY9+t7rvV)!UO+kINOQ0BhsMX2A z0a`nMj68UnzG-BDCBk2ym1MWB0vw^Q3k|lM^VheGvui#$so_XvHBR(Uf14$1fW9o* zuAM^!%0nG}Mxi2e-js1xCcj1br2I~D%?AifvR;Qlh zK-y&x_JrBSIJDL+NKr5rvz=IyIzzuWCq#Q0%qmAcRSTHtp~O#uhyGsG^_jAD|tCXSM@QNp;h`=7m_F z!EuB1xf6peX9wx~=h@X3x;j6^k}y~wI^V8s8*I*VvrBKn!=%e@WHi?&XdPAxeJLy5 zJj6VWTB3&Q9nwRzd~np1BPl4r`Ww7Jc8~TzsM%ar<0RwYu`|q*de2p_8UU1 zb#0^SCo-I^Y%Ze-U7s0Z&NSRZ8Xsek&{_^Pk7=u|T?7bo-R_EYAnXcfJt!qWI}ML* zoEpy2_w z#}Q=j2{l;lg5$ax$9)sjtlCKQ>2-QyQA?+0`h`h7wSFUOr@0&&D?wOfZB?vQApP`6 z|6og}QTnte?AkQ60+%DB|7~mGamD=G$$kLHleKbzQWbsCk`OHhiwv9DX3WeYcpOCa z4evMU8AWQ{aG~RXMTcO1FM-Ds&~%@90ooCGY zp0aDDfIO@@)&oatHVNwMhZ6#A;~Wbkvm}huyXM%nqY|36;do+At;TTc4-e6f;(|0A z0IPR<{GI^8)Ik+p&$9n*><3GSaQ$qqU7Hzhu2yK@RRLNtJT@NI|B(UO&+xD$W;Zle z56=jUB3?GMaR{-&HFDdl@Yp)HyE$-@rbg&n!tAzo6U?}}one~-_+Q3_Wzz(G%W}J_ z>KB(|6`82_%d@-goha9NbAl>ZyQlf86ZPYHcD1$cx*|jinPgVjSRu3}@YuE%oz4Fy zyt+dN9rjF!B_vW`@Qhu{i8PxD-)huplw*;4gOyy$My?F8WKP!CuC&`;pKMm5?m1X~ zove3VWw*ASg1#_^ZqpU8W^|W@!J1{dBN67hbpSmsgw_QJ4K+4PM-l2% zJCUr{;MzG!v_R}L&GCl8Yt4lhqUVhbww_0*zuYkm?Wx^2!yL!PHb;wv$3At|J4^|% z7Q##6HbL{8>9{KKNwpE&bSwbx!P6NK@#OM!YoA6d{6Bid6RQKZ=r%`$Ii@R?;6 zVJ!F76nMr`^RO7vQ`Ky6x#k*^O10>#o)6Im%r-|8RzdDC;q^octk&48mck2VBVf(m z@j{69P`sJeY_K?ZW>dJv2WXq5r|NU`0NWXOtoQ8+g87FP)qQ=47M5U6KU5K$Y8@U| zVKgY3uv~gL0w$xDXf~*^glU7}aiU^OV*|1n-f(!>P7MptPQYW2TlJs|fohUIVWVA} znq+n;&IOBB5j>_a_iNw6W8G`7zFO;Kv&Pu&jSjHI!owx|?dtoq0XCRHW-a71^~88D>p1 z-SwvcZ7;lGICgEL>pizP>qoZ?vV|`&yQA(RrL6_*gXCDvLjx=)7U*lY+SLa7xve2u z=woJMTDZw}T?r5S#%x7?Ec&8}eYKOItfaArQyc1PaftTtrrF&N6eBtb@nSFt`2R!t>`*b=Ri?EIk(LXGhyDi3{~*uiLevg^uF{ zv)h6h*x!WbAa|LJkB@FVx0E(S$e-6cC8CeuD_846U~}N zrzgt#*>7oBh5@sw-V5VeiIX(#pyiyWQKb?+5;<~W9Dt%PScSKdS8dfGZIHXHqK zvt5e-?P=8Mfa93I8oFuo6uHE`zWw*@?5Hss$rG7pd)X>LH?h8JjL;N{n8iRt|< zLogtZV0Kd`yn)8qzJ(B50ec7B$NdG*td!hSy81q84kJ}DKe%88^|dYl?Wb4t$0S3j z4=0ZGCxm>BiPv!{>d%mE3_@&|zn}U(P*&d91=)Us#~Lt=o9?^MQ+wlsUCE$I>X^4MGZwG0{GU#}2n~*;d_k*8?H8k-27yzctHq5}FIm zxA4ryV5fR6b2J$)Shi{K{>!Pjt_9_l+fv&+bDrp{odxCLF*-wecQmpzL>uMwY2G#i4% z3$|7v6v&$$i&q{C(t|JiQk#3)P&@+9t98mVYxriQ=9xl_PaW#O~$GinxZPrB9PYw^z;^6UO zUb`@AM?i*xn7iagy5l;;aUTe84B~KA!o~Voc%$H<9dPmd0p19BxW&PRvd^=!jl|&& zYM>1s&*Sz{j)4qhUg3jyea^cfw$SIy`S|xqkOOM2NqjzYdS-jYYvyy+)r^ZrAL>Y_IypeaJ$1oa36Y=#{`@-ORn%O&Moy2*&1{wN&&u zPu%V!0m}Twtg-el;O?G}qh=N8Ti&zVwgIpq{&pVL>!8E=)Jq$>)-ii{M%&@Bxoew7 zZLYgkgjgp$kMl4(J0GFGtf1`ea9yqOwY}h2fp`zQ5ndpYm=7JkmL4|q*#5L%=XgB9 z8`Rvd)fxTWrzN)IW3QG(wBW~*WN&6PedyENDT7t;q})2^MbV= zFPf`}%B!@N1dpReH8xXQ;qln!mGx(MEZ%q+VD)+lDcR~;3_=6Ju@}T0`3`b;e_Ir* z0XYt^C}OYQ!V z-tSAh^`)(R?ppC>uxiuGzYNimwwZ+*XK6XTO`q_UUF%frfLy7Tz~dw|wlcO);Bk`G zc8KvnrR{6xrqH;)YO~;(HFZ2EssQ28Fm@Z*#*I7|qCN7ud11i%usJ|ot{?t7L@NU` z#{uRdYCh+i5N*tMlhy8rtk0A19?tp`LJyfYkW;_yY3;g$+knz}!P-oQj3(e6X8}C< zgoocJd~@5yZppR%PPqUm=BK{Cs()Y0h@JYi@9fsKh?G+ZX|)q@Io9xma!LR;W+%T7 zv4ro^Tm4|y4()QxU=BRz-3~A6@jx3Kp1!$vS_+R1YAlnsQ}8&>Y8zA}w@@|p4emr; zhrMBDRBNjiG@!4x4Ag8TtV7mM;o)H;?u^^*F$a4??&7TB@O*ilvaLjjhxpr+I|j%W z!umfiP~D?9_{pyI-Rqdo=o0IEcs_dN*nk=8XJ&<4z-JMqTS+Np#K1$JJR zs1kku&vw@mfQJxmkyZ9Eo_tq>4hJ!uB*A(bA7J|g z9uHZ!&bUL~Q5|CGvtPefZPy;(Z$8kq=p#=CXj|bui1e=ds>uP`m+)AYjaPeH+XLoh zt!`P`3_u?waTaP*+-?cDJf3l%Vtogmw_f~Su=YDbtho7X>XCzHx#kxfYvFO88LO6d z4jxb3Szq-ruHkPg%EVeP=q-E;TI;QacRTJfywSCBp@$SDvetVAUR?_rc-+|XFo z9M#WWwrghr&GC<=!Pe#-bE4OdU1Kqr0oofGokY|?HNg4`+`hU?L9li6yOlzg>nwzZ>;5&*=r3Oz zWF7jR!LJW;M!-DeDHEX@ZQplfpM{WFjqL~xHHy53kXfOD`r*GqtSc%Uhd70hQI_WQ zf!XoK6K87_Jh?>Rf@~FVCviq-mk{zsL)i3_aRHjwhvwM98i`ePF+8J@=vfYZsL#4( zR~zX&ZiQF}oIpb38kC5T9ALOR*ba|bF!->q{*I~O8B4C(T)3-h$a8_Jv)aqN;9nit z)4KR12DR~wVf#tryTI!J1N8(wSR3$>xfOEaXtm7!NF2AQcIz(CheV{48f^LEV==)A z$o~@zRs&h{5sWZ{7ZDt51Xa7(VtTG?jY7h z2#z;$T26m1mT9UT*-mOmG~^3536@FMrxD@=c9JU>7Pu$+S`K|7wlqLH{E67%qPT$? zY#m&Q0b~YO-40gP230Sys3D4;`y~dIneHtFLyaI#ep4egM19m0VaivgbP+x-h)XhM zuOZf3UvoReBddeOxyFcp+LV)~v=nL+z=@`8Fy&iQx`5ccHrRzJYEm5 zlL!c~RDLV2x#9#ne}@%RR5Zs44*UVFZ`@cHArx(d8vTgH#|R}LG{p$LUmNOn9$ja! z9E2t^qZH|d$%EAMJ^9@XbOvPQw{rF-WDYa0*> zH1fD&vtJEw5IpP-=LNX>{A!jbhlYa95Wde%0_BLY>QP?>xV{XJSJVcz!C@FPa(a^Ma_2gU2J?{tj&=$S4qFCvW`*ULSK?)$>&! z;o4Tk!;Ie*CH&4}cLDYX#4Z*Oy{^JzvA7~*7uxHRV};{>C>b78;&Cn>M(l^j#x?JZ z>;GZqyS+OO0trIA`PJ=Wcx+}DW1D>lUN3mHkNLFUL3$gh`GmLgWwSJM<31H02ZFiv zS`W_`p83@4E1B|kN#m|KYQj7HmGpQEV>y0BbnK+sHS3?4#>TOE)7(((=!9iVTou<4 z>6%}oDAN&HU-n09p?avk>NT4K}Q0b+L_{IxI zuCJ=*ND&=W?3*Is4s{&b@{%g{cg5Q3B-C!0kOBDBwthzG)@Kn6Hwx7*BghUkzX9*! zq#CoXw$=2LA$=_~oy4r}s@+zM*kMRpJDBk$i!;~&qf}d8XVrLo%MFN|nCh*1YH2_$ zoxj}^=nQ9^c`DZtOf-VFSyr|7v4We(?xA{G_FKi49yq&T{O;RujBy-cpT7J zDFz1ED&hUDF8m79tG+n?05UGBuPR|iQa-`?0G>J8kx^|RHuXebM%ctpJuyyn8=8Vi zBEiQ zya1~geyy%2@7b->5bB|aB?enpB81;=!f!I2LZ}xXuBbMl_QqNgir=;yfy~CDXw8Qw zpB!-K@Cn>Nb0dL04Yn5@9zuVn;kVFyMW&A$?0Oi%K;-`0Nod*l#XFAShP=UcErFL< zCrt}|QD9$d=X+FTlBjq9tMp<7jg~OJf;)SUXw?^kr?rUci-To1;n*_{b_7AAPi3QE zGGmPV(M0s~MT-UFxA(Y#R%NWSemJtPwg!{~QxS8zV;6cEuAP^8%fn5@1V2oOtfnkK z(hn2jFoJ=ix+g}FDt!8(uL7Eh1^qDJ_BS)S*V?qXid~RLUz~XYf_0~POP-Z>5|k^J zGf%~}-My+Zwoa84ewkrOyH|AWj|v|_EW6m^=wrsJRw=c5G8u(9I-n(ggUosw)NVAI*47O{9>w?yV!E5SHUI-? z7pT!JeA1%bkZJG)6Sv91_@%*dMl)Co5FBFmKW=+5WTFDmB?+zAh^2wS+Af65S%!tu z@_j4OF9`K(E*1rG(P}M@!?o^htzz@XU!LPH#343fAjaJ|{0^eIJaveweG+J02I_C5 zT@#G6tAabIP6Hah7i0CtuPqKT5{Z>aWnFyRzv>1582li;@|R$2vPKR!UGX zIRs*$?8SJgsZeM5^P&9IRVVlhWc)%IPi6YWP@*TKE`hTArG!!&LRYEyrPPDXP!PXV_j_wK1gyZ4=`A&U22Gor!qcN`c(Qupy}k@c(w{5+e^M*r7a-nQcqFP_vY0$u zW?Lk))m6qXmb|Xoz?XruHS=Wt6*3)_e3kV7Nm=e{3m?9if&ZdRpv!{RKAG>9)#rR90h~^r`fVExdS`fm&t6Yce5~ z{_E1G))U1^s5jH^k+`n51OHTJI|c0w|GG>^*Hxw) zA~}^S*l6if89x@v{Np62(jPB<=qw{)galM3m>~WCM45h~OkY=7fk?@zPU1$2+R_zN ziGs^))2PCKEHK>|rh>*&Me$e_J0-C$Rc)zi!etz$B@?AH#lKL-XCR)3ehfnW-E&&p?S*OMMQ?neaT6Yv4vG54s7; z50#aCN&0n_XtU&0t}*XJi9Y1ozz+gOfhS1up>iahkv^4Y@wN2-6J^qG@q_vUe((}| z5z2~Qg7QSJI@X37royMLGT~p6*HxbRb;ndkdJ8&MkBa}z!B-2rw!|yA7D&u{jJYGL%*-;1> zpMO$jcv!~&lk&g=5YLVcfiiulOi$&3hDyJ#GTkH2o$%8Lm>Gx30>YroGZH_XMA&@X z>P?!DdoTXrj#U}QSgEW*1bmh_LGu3{WjT?uoXJwBKv`rof0$}s_hJB;Ar{I5$H@f$ zq>P^>qU3dz>60X<@`UF=dAu}db8aDEg85KpNS6s0K>7J6Wz<3$|L>Fs%$Diu zDhK7#EE%yB%7i)6r?Mis(yyyb_q60x2A`2Wm8-xS=~G#bkp7)I_)b8d8S-TYDx2zg z=~G#Ob<(Fgi_(c0RKHAAn;7l+A{o+bmTBrL%PIorF}6Ut#Jn!kQOUPU-61)ZCshJv z{sWTNRpvX$Dagvbi3Ch@1V6Z@RmcofUXH$${{Otn@${b*%riMBEAmg;67g4M{C}*D z@$?^O_+LH1f0I6|?t$4SH8KO0UGtaJ8&EE{^)Ue05)GhC-%x5J4h(##%-2}@|D?=! zj~Sok2pGzUCNd+HPYc>W-JrcC|DRR#|Nm@(|6Cqhtgk$Qx@z3V43`oAH`Eya|0fRI z0%ts3p4h)pbN>CC1jZnXK|vfFGo;Rx8Y?vp$`6(4W=Wq)f40dOt>VS0YEwS` zQIf$dqGBO7{0J!-bfJ&YxkFjx<1&6Bluu-q%XI&wEN2DcneQ2?D`k2rM~5!?vsSq# zu8|3-%qXPhOD&M`b(LtnwY&UH-U3iQdN#p3#Rg{y$Mx;Dk(n!f1a9xEg&TBdDy{DJUyeDLIt~{2EI1J$^9V zk96)(@+xp1@F$t>7n#nXRt9kI7maJ=uxRYLSjZ)rsIIcG%aT(WyoMhv{4Xdgb(8Q8 zWj^EPLn_m&*j_NbGq)LkS96Xqf(hzFxe&WTnXxI9t<(a_50&ZMrTz1{xTtz6$z3)mFa?|Pi1<$^r?&wg)-kT8ULu% zQBeF-!n5#`2ab?B0m@dL0%gW%C<~q;{aH|c{{JW|7LRhMS&8xhb7aAFl@*u^&I&D% z@&7Bz6MIbNqw;{6(x)OmOIavEUF8gT(oCQ%g|Y>5WxBe`11tk)!ONk10Qsy;_n#?t zWVH$R7R*q$-u>R;mcaVn`u>l8`?w^p&12&V=UiGITeRRx_s3`Hzr5VqZO9hy;|~?}n$z{M z!wKEK+0t$Q&09AH4PFp@F)n}klr!sZiIuJAyjrZHxOF#hFsecN0b?9=Cu7Fc{#<>oy%p=lznSRF4)w&5>CD~i=e z)Oo`FHGtS+fXvqb(nUFe+iL*cuLCR)8LtDB5mXX9F1)q_q`wZ3w;f=iI78sM9l(DF zK(@%;0dSh2nqaZ;+X;}f17O`wfF+`ez;`D=*e-yjqF@)md4d}RIbz6efc#wm#k&EP zi5h~?-2jnq04x_pZvb2+aM=T}LPYEVD0~B;lwhUM_5y_O0Z7;juv+XRuDve=skd|1TOCbd>|s;2Pk|Gpp@W*&?*4J-v>yj z0QgAkBd}EfczgixiHQ3EpoE};;FNIx5FqvgfXoj8PK$B^w+{ilPXL@187BbB2r3D_ z5MCz%(oX>7odoz&oFVW$3E=+`z}F)8BY@Kc)db%NzmEZOJ_1wp0GubdL2zCS`4k}k6M*7R0e%uS1fib-M4kfpMHHO^xJuyi8Njb1;xmB4Qvjs| z7ld{iApA3cgwp`Oi+u#P(*Pc40R9khX8=kFDhRF!_p<=8X8Ok3eN$Q5;PIow*cYa03>`1&{XUruzd^Q@f|>O5%(QH2|)!x3*r7fKh=yOEo|b5m60L_zOTOK~JIm3J_imknk%&FR_on_A7wLZveeT+;0FS z1Qi5*g!=`6*xvv$F97(8assyt0Nxh?`iYE-0A&P~1pS5A?*Qo+0rGwa7$D9Nc>WIH ze+eK^ln6QGn}gwSdL!mk1()BubU`v`0`03O!> z#)!CU03`$!1mlGJUjVV!05bmq2p8o9ZhrxIUk8{VGOh!Z5mXXP5?(g|(ys&L-2j*@ z&JcLs0Pw#FFjeH<1UOAlO)yRP-2%wD39#-Kz;sbX;CoATc`nTIh&toB0t;G$?hUxH zVu)%P|6INWZK1-SC2HV{P!%B30uV2XEC5#tT$}(BMT8STp#`9nAX#Y60O3vm3C;j1 zVjqFc8NkB|kS5}+03`$!1oMP@J%Cs%KxRFFbWu*=Ru90tKEMKzQ6Hd;ppxKm;bj9z zuMd!C16U}|5O~@E{561Vk*fimCa5M@Ec_Y(m}}$aDqB7v%(Qt^nRm0oIC)rT}FGl>{#c zuVw)0O#$+n0jw8i2t1ns_%{dGC~}(voF=Fycv1M>3y{+sVBNg{FN-Py-+KYVS^#Vo z1uX#16Wkyu6hm492|2XLC8n&61=YY&jq4q#n-fTN;{z_&d> zSOs#T@~TiyDH^jsTIJ0NxixodB*9xZDTufrz*dps*7_ zDZvS$-476cA3(zW03V5c1h)GDJURn>BH}s&ln_)9oD%L`0Af1>WOe~KEy@Ypx&U~4 z0-O~Yo&aS8l>}c1FE4;}Pk=lxfG@=v0#7dh|E>UEi`=dNrwOVFz7c-i0CKtltm_8w zov0%4?FJCm9pDF1&>i4B!3~1*Vu&|Des_RkZ-Adf4MC_kKx7YqUqn$4fU5*94*>is zA|3!J>;X_pa6xE20m2^uNazXhyVyry>j~iD1Mr84^8qL!s35o^+P)1Nma9w!y21tJpAg{Ltn-5i-?QOy4qc@2ELr9{C+=r0lG(k0i zMfmjr$ax50T^|5vQAOa}2Oz93Ks`~=7vMa>4Fa1O;tP=97ogY|pn<3%2=xVs^aE%l ziu?es61emOXe=W70TlWHloB)%+QR_h{Qwdk252hw5!fCE@aPZFT*UPUC?TjIXd&GF z0b=_DWcmZRiE;ure*o_R0IfvE0Dv-rN`f}R3;$z{NFM-@7XZ*!oFVWG0Pqh4XfJXD z0ZtQC6Lb`QK>#^{0PBJP?h{o6zCi$C0|7dVf`I_%32qR0iXp)O`2zupg8{mV8Unmu z1MM*gpt~p<1aOtWWiUVw5iuB`a1cN#K~JIC0m26ZB-jCZiG2h%JAg+BKyMKj0#HIw zLC{CIhXTZg0Az*&_=<7@w@?7@ApreE#t?uqf=Yt^!fPl%`VfG;p#THK83NCt0RE2v z1d7~808SHB6ATo7!vJy~0a!N-V34RH@Erya#;dJe6odhsC%8cnDuxUP$PWW39u6>6 z)DVOY2Z($WV3;U+6yPd>%LstsB4PwU;iCYh1S5nt5+Hm8K*C6XQDPr~Z6tulD1b2{ zZWKTXK?T7$;XWE5b`(J7Xn=50PT)2gz)QAA7xD4YOLN{}qHNdVy!0TLzwq=pX<6i}WL7b!Vn$aF}q z*hE<-YA8>Okui|vqKJ|w)EST!B7*Xa*g;t-w3(1qB8swF?1Ko~OjOPz7L|Ke#Ki)X z5L6JX5$@hz_$LYefd-d2y2Rg7BIRStk}z){8Tg4Zz+V!pC@+gD$}1u$5wcknP+k=mDTQK45~N6MqHGa0l&xZ9GGv=5q7(~t z4&*fvL3v&5pllaf3Jw`Q2Zu~Z!6A2weFU}?o@*+=ZV{Ktb0w%C*dyH20Af=CGSdJ` zL^*+58i4m)fc+w4E{__D2iQM_9&S7zmazyy0 zL*5pvC`UyVX1QIwCwKFY_!bs^*v5l8t{9HyKS?pct}#2m_LQBFA{I%Gr6iVTP-%i@V< z<21eyUW>ph#Ujd=;tb_0;jwaBHM6Xz)32)`#F--=a~??e^ldl9q*@`EU#{3tF` z&Wj;WLaM|j%1@$(^0OGZ6!MEGqErj@DafxPg7TZ#LAfBb9LPlxMfqLqqg)cMxsX3Z z9Obe&Ot~W5mqGp%b0}9uIi*H)cp7p|WKjMRCn?v3*K*5v%MFWIyxcO*a?>KtQg2yA zuRO~*UgPtSN)_iQ7U8!7;v`m4oJAGIDuSMY)Ds1i`r;zRCWfqpXkrtkfvBN06eCwb z8i^u^xVjQ;?6Mkd+*m}c1}IzwP)g85XgWanYJdbCpsCnLVABCSo&{(w;+_R4A*di| zA>5w>h>Xb0OSdPw&DzdrvUKJ2WT&H z^8rp1R1cAU2 zD)Ew{+K1e|#6A{lTaV*-Y`}4Pi?|H{B?J`&eT4f)fY=QHnHvFoMLB`nMgZ?k0R2S9 zCV(=6N`n5v>qUU{O#pc>0t^sm2s~c|@P7#)P~^S@aGIc+V4(1O86f8+fORhe3=&lY zzApoWy#int1+M^{C%8cnDu!$Z$bSW(cr(CIQ9}^A86fgifMKHORe-AmE`bkWd6LO6()B6#;l`0T?6Vwg8k6R1l04?ppz3w*X{r1qc`A1a4aa zyte^N5E2qKd$GKS0<4fTg0~0Kj>I8w5FG$U%Vo0|3Pb0hWmxg3yBik);63MNuih zRRWhc0al2JHvtMu0ZIv03hga`@HYVx-U3)H_7T|L0`NEl@T`bC1W-ayL9j-+9|nj$ z1dw?cAYYUdxE%)YJ_4{-WE=q~Bd8>JL3q6lkbVRp?`?qf;tYZ3+W`JY0XB-=tp9H^gDe9^w8z zWbfWN?_0LI;N{iMV$xZQ&3y=7`iQ?;$>#4tL`|PIJ1z}>@Q)X@HrTuAyd_vQ5^lU; zu~`-b?)~6%%i4M_9TAH^qRWoN>kRR_$McrGOyqKUg8Bb)S3%uG)ICnKt&dH@Z(oXY z&77WKiU!emhadjxE<0he81S8?v*p}mff9Qdxoc1j7sRcYf>K1#cb3-T(03M__2DRR zR^m{RP$A3v5osE*2>swWC zAMd<(>Tk$pT@Z-!jpKEQicU&NL@V5vWc<#k(IPRa@o|Z0k=kmsHmb4L_Pgbfifiwj z22Qj0241l^n+-LIRi5#JY?rT$<8;4b`Ni2~BhC-Mh?>1(yW@Bw@Gm58w?k1HvR3UZ ztgT4CVX?JvFEJa6eKKusVn!6IHNHfwxM7*+{@%XZwM&?d|0O&be+J3)JY%CL#4k=x zHf!KP6l|Q>np-%|M{w`qak7k>KDW}z)*}3!+gwIYT+4cHP*Hw%}j+=2jnup_mbGNK9|958|h5vOnM6v8e_c%GZ zJN{?t==iuEvr^69`8582bPmmlEJpPZ)h|NR2lJ7}e^^b13st-s=hulMpyA2iN% zds8Qy#SYn{>mx1=GrbF#VLHU|c?I{ji%#fI~i%Pg$xzpNCRs%}NE*X;eW znNwHQ#qr-<|Ap688Z$ySi{91(MYnHn6kW7;YD=fydm4nlXZ}UO_RoaR2TuJ&{0C0y zS>9|DeEvWiVaH+oc`-(%@wqG+|8R1MWLLoW>(%`IY5sXCKi6bB{_!mTcAB5RB*ULj zD%&LETgdRwc)5Xm+d`IdQzpbbS2{2jpIcBKgnu}9pJYz**Zr}`DECX|ELjsUH_7-4 zGY0wgj5d&j8~SiW$uM_k?9)BgYb9e z`0hql)&-2pw_)(bkNi0Ps>coCeUkCbWDL5)mhz2FY@KEjwnBKBWX&aO4feFm%-5N* z4sBq|WxAF!od?+KF!qWY7%S5j_B@OqzMY80@DHxW5a5&LAq#8|2QO?jK78jH6Lx@w zo5*<084K(P;~&|w|M^NYrt1Vtkz?V0$?gNQN!D4i`@tGY*2QF5#w(;6OUQSjvA`~{ z!*bAgf$@wzVOPL7pt?!sh47y;owv-}73`{HJ!HCWU^S9C-lNtXES-Px&kz6hhzI6u zh?fa_N!A0*NixUZCOrUVm5lFIW8R*yH|6+v2#n|C1A9xdhh;jx_^$+v1HM1s_{C;@ z5O!Q93Hgq;67keSnkuWw^QT;7eB8F97@m8?I)tz-os0b?EfVQnM}lj#P4 z@i)mitAMeFfpNAx0l<@sfpukGw*L|dXCTb= zozvw>$*`$amZIbUDi{wE3(H}ED$~UwoGV!_82;h)i8xcqmdkXr!9pd=12f(j7!Sy^ z3xuwa2@??JJ9dMh&q$Vt@CMczpOum&AzXk{;>=hjSu(=!$#Jw=vN>Q4k(UEcmn?CjgsTa54+6vzR^X~n_y1k4>_j;B{8TY~UP z%)X1tOQS}a*E!b4aHKCel( z4B=s59C)10tl-lyo(RTRma<*K<$%xPO!(O$Ssud85oXuylxzjUQ3$gec1iXO!rPFS zP0sa!2U!VYtFp=8kZcvgY*n&721EO=hQk8c6?X`Mh-5E-jg{_B1RN76BUzi-JvtO@d81&%fG_D<58D9S2zwD`MKjccJ%jLaSRO15 zHWxMzHXoJ_N!3M+pU;|)w zSU*?@ECBW}tT(I=>^@jKSX-DktOKkk?0#5hSVveVm?x|o%nQ~P)*a>p>jird)*jX+ z3qN|m9)PuhDKHDn3FZv5!s@~JKEj)@>#zsWDtuLVH&}O=H>?M&C(H--9_(Y-2e6M| zeE-G~*gLRt81Gj;ft`S5y@eld!`_FTgzbe@z}|)JgYo|4FzhJo0IU?o7ihi$<9*7@ zu+3n+7s-dMg}ne<1il#d1nf!JAapbDQ~0XV$6$}cCh&!r6A_pM<2z30!sfyF;`5!b zU9b}PvtjYD1Q=iH-U8YZ<__b%2=6`G!g?bP_ZNyU%n#NN_AsnJ%pW!Y761!`@%AFv zg8lwNWaNFtPS`HkZrB^JJ+Qs77huoBsxWs>qK7JBU&46b!TSu}S0syz=bYMQ@y%En zuyj}}SRKs|k+yf8(Q!%z@!$iiSvQ9yH8GngwZ z8*CA5G3*K05*T--+=X&moCzz3y$j=2iPur^#OA>bgylC@U z`6i4P`uAYmrtrGROCB%Gyym_Pi-yI(X252`&cl9${Q~0#zZ&*4>^E2y>{l4BYRXSp z_^}E0A}ky>9>$loz6#rdGv5GP593Q@`4`{IV0^Q!9qA&W>97nKH~4%^|82u+Fe9Fi)5ljGOvyu&nO*;SK8ndjQrG<^$^m>kWGd)*jXYwip$86802~8~a?? zT-baVH}G>{+_Z7lGkp-I!PdZUghCp_n!s$Z24G_l*Aw;})4;f==01H5D!^Nw4`AM~`(XFOxP7+4 zEbMA}k4(44VT>fu+Lc!s21Eus9g+C@;czf4u?~;R}ZABODElfQ^HV zg*^=G5A%ohgZaXE57z=_{GT1ISpW{c2*xXHCTs|7DC`l~CS-U9whFcy_AKl<82;xS z1^}J`vZ0vb_K?FL}$&wkKwRKVcba$fZ1Vz zu)(k(STJl5tPL_nph6R16Jgv@M#3h;roy6N(_qoCQ84Z#n;=g z_;hl)sQ$sJbrzokzJY9)VOLV&;zi(2nWIV zKi^z}U4~tOErun+He#vT2IZ3&K6&B2<_@sk=$EH|bn?n7MrJ;0;oBVfc%>QaZB*t6 zOhwoNQ(!k)LD)4|28?e)b%F8W#%45J5$q^z3yj-)-bcIyy9HBF(VI{eIuSYvwi#hO zI>_SxZbk`@rr6Ujn`q#(3Uce*?x_aQ=@*{9lgJU>k8f zo+b4|#It-ioWPH$=nt^JVApFE6U_m5d(FG)6htn6u(gj0_|683h6*gbYsdj3u@qtPtY_3o*I0aM%}cF5RWET7Q_0$c(=<31-!TC-7uaHWGQ^Yz$Xt&U_5AZ*po0mp;!v* ze@B=F@%EbOna`1joP|3W{kq|QI!+%xLgM{O-Gu)t{I|A5o++^DuxQvc*ksr|SZ(9B z7TYg6xmo$(VZ1n3?bJ+sebMRv>+DS6ddmL)|M^_Eh6aTq`m|syqonnNv{;gnq!1!) zlD)DkWG7o?>um{T$(}?q)-1zVvy6S2tYd8qV-zO8*Zbc4nUAk;&F}aBdpw@bz4yG& zIq$Q*-{+kB`Sh_-FC+DvN?q{j#;$KFS)1`Lelu7Lyuc=qNz)KDB?Ffmz&fxVYy??= zTcjBV3(vucAOY~2g4Y%!0K15RAPTU5!Ots7YiD*3T>(2vc9=Zu+k#erzjr$s*n_5^ zF~3J+uZdp~RNF0gFFC(t=bK8K@Qjnc7SZa2K`5{50rtw!5`o?_#M0g z&%jgg8#o3Ez#(uD96ZEpQXu09U~k@C&$%@}-;W2(N+L-~nL4``}k_58MTpK@oTiUV!J|B`5|T z!3Xdjya5NmU*J#h4!l*aOAwZVPXNDxshYz5#?6MG)>H`qzrU$61fTKDKzXJ@h?mzY z{1B)LKOu@6S@v6m#sI%osj3R_%a$ts(Hs1Fp{h1u<+!zK;o1z~mmXF104r*aunzY> zFFg6dcL*DT`hZta*1!tbfCiuuXae~Bfn~T`>=4?5??E&05qto=D7XbOA(MjeGT`%z zv*0w~-_<(_e&pZN+lPyMup6{Sf=q<$Wq84o29|-PU{0>$QXv0oU<=>? zc=a(2@Tywpo5$fg7VxTM2*^bGfe3jpN3j#Z4r6_7vKrpKx^OxxLX{77PJB_fh%BHXE22$_yLD)fCq2~?LY_632;GOfG_X^ zU4cIc0KtF9j$O4PH z3cwL?0PF|+jIR%Z!wNb%e#YteIX}~d{QM_y9C$(*-E+>HpYt0p-!p#{F z4i*9KFBg!B1Q!s70`9XA&<}J5+>bmk+kz<25pY*t0$+~&fw=zx@QjH>=m~h%aJRJP z{=bL|o}WC`xZfLs7%&Z-1Jl7c;00J2F62BY1gz+n3bInH5X(#klfVsd9b5xf!METS zaD}f;@gMigO~7uLBde0*2YBYExcm(~0k^?pa0fgDMc`L(58MUZfDgcZ@CdvFufU(+ zJ$MJ+f&yZ2$n#Z9EAzyzFnt~>v0cZ>wf%?E2R0n@@`PFd2+esr(1yly#0Isb8 zLJ?F_?hO$R!}D(u)&_NfF)&x|>mcN9YAs+2YJi%+M7ic?9LH&yTDM8dc zgcg9i-Ui`!fNQ}@HUwP5>8PwNLObQY1wwnkLx%m91FpFee3s^@T=Tsa*B*cm9H;Qf zBcDLJ15dy<#7hYckV!{ew+HQ%&>LX~z(*B7fKFfn((n$79c%=`a1aD~f&jpq6FwQ> z4N4Eddy-xNiz<0$^6>(8E7A_A7c%3c1wLX30es}ZM-O}*33P6~F60K`J{k-Kyc6Pl z27_T>EQkZKAO?&9qrpfp3drswM%KP3GGqV2>xglP{I}T@kN5_Vtq%eLTj;Jx$EH6U zaXUaFSOyk>serrrJIK=gGAyH0`3YV9yOOin3|vkJ)4)=&1S}@YvPwOsEXO5*G{9x- zLYSjmb9skweGtUsdOt#Lm>&`D1$iJB?8CD?2zLWBlwS)W508Ba^T7dd7~BRoKmlM~ zQ5-!gtE4gfe4U?Ajn9?3nH|UFF>n;z0?x?%CXM}EsfXD;+};IuK($JkPvBd+`?*pF zvr;@N0q+&~x^$VPSZ50F>{+d#y}AFnpL7Wma6JKx2jhUQ)|_B0?sc_`SFYKD>uSxJb9YV#lK?k) zBABX#{CqlK>%uL=MxNg&N)K28U148p%L>f_vjHo_3Awg9MV8=tF_;T@uyJJ;fmDzJ z<^f)jaG~>YoeUO&1%TtGq~X71K&LI?nziO<++QmZa(8h5tyZ4#GAJF_tAG>O2sVH$ zkPUW#?O+?&3bp{wi}U@`bD#^I|4E#W$h{yB>;bz$F4zTfKn97h4M9`+l}G&Q|m`inhi4MYr9ur4zPdsDX4(HEM}wRBS7{e05)0 zD6ylZc3-4Jz7Oog#RlKm!>UsAYNDku(4Lkz7gq`&?8(JmoS-(QKu57If>ZWlePKfj zYP$joSFI` z?|_wVOUiYF{^_kKWC`l?qSf9uVt`tc?1nWRQp_<}-1K&v+qVUEOM3@<9#n)+n7fPS z8r_#1`h=c;ulaS;b3yHB@4{KCwzyFSB(%9o9-opnExvJKq?w?0QX~!_#t6Be)_%^k zj~eJIsI|zQ)BfZ}#hkWKkx2b(W5#~VO49|kv%Rxa{!JxjuxnUW3%gg#sR-4nchDM zY8RBnIXc4P86&5ms{$6JJP$Y}s2%K`q;_lDhN^m^y}Gp_O*e!QZKy5owPTP1rj5WjPv{FAv@KZztP9&(%$MM&%(fm zfm6Jz?E3%-SF|0b;X}l5uBI_not!gE1|kMyiEHK2nHI2Sw>!(@ZAL(q1{2nd-v$Xx zPabcI?!sT4>6SM}5>iy}$bIN5*QHogZ9i4qI~yrl{coC{_oWb|)%f|zt?W=~;h06k zBM51s4Qsl&E2Tn0*xi-3cEnhV>_`{WL^A`J>xJFO&IgHCc9WaATB9TG-j`Z%Ww?nj zYcN2=Az|?j5>a*9U9hI z%+uWOBe&!GX+{^lOxmRi>O@BvN({*4U~>0GR&u|aQ;e@zPrE8uZn{s`eT9xaFC?L4 zSz1+23=brpt{urC2@d^=FTC>){pgJ^#%@SIYTN~*YGMc_cY(JK4$W`oC+4Vy2Vr!l ztLP@Y3L|rW2>umDe*UP5?i*`uhL+A=ac3$9DqABoBfh*i#UI|lG+b6~TGQM{W$Gdg z3rJ&8WrG;Dw3BU0GHi-2hOjqqY|X0KhtmaQuJwR~2_zP;&vU%8Qg2(k$f&0Q}*lpU3ae_XuftYhxdctU47IzK~<6=K{RyY#F#?bq!} zuR(!tXhZ;JVI6WDEY_ur0MSLTkEEh#(VU8Lqxqqqta@^0ZqVP83xkkSsa@+x@(hF` zVc}FZ2;y;pqQB5Fk_z}?&q%rzh|Y_Or0U%f#zsX&l$hmGEuand=aCfN1I1#_@u=6F zg(NRif^Ocot!dpQ0g}qh>N!tJ0Tg8J97k>Ypy{&XWN%~ithc3C z#sc55X`d zuiWV65RA#}zG6M4MWhiFfu$Tz)owd3jem8$uB)WFWJFqzr?S4#!e_j!#mkb&yJ58| zyFfx2@4q01-N}opHg&(9-iQ|rO106Xe*MH|Lhb~b&`)&3-|k?0B#eru3;octiSe>+ znH$*fd2PR;i}dy(Ii7?NwCLAsW>c)U;Z4wt8SxYl0=2dw5B6B!b!)ybDq+SpQ_1+b zzzQWJrY2%`7(ckutVMPcy;@xoXiW$jc;ZBQi9Cdv6UneY8cUg@)V;r04@=h({b4)H zac8{zg$Csq05+>|%-De(ovbD*x1x=E%Frcf9nUeH-PUKc1>&soP{#)-_V!J{L+T>kcULjm6zWo#F_*nPi3N% zV^Wl+P*$aeTEI)*&5&RVc+)*-*{~ZE&qIRk z5LDTdLIse}7C?e`be_!~)Oxx31MgQAlW`s~#)!FoeZ%qI+pE`=a+lKHNulb)VQyYQ zf>&tH#XX}9y@#!UgtC)VQ@i0qRM=OC%6cxlpVd0MP!9?)^QJm@#am&H0~ShN$R9UNQFaz=-;je4r2 zDfuvQ@UcEiG3PGfNgXt>vMbV5TOrTNsNmzr));3P2UR)uZ~!YEXz5FlhS1RkUFw3cIn2-i$<#|F%lb%H+h3 z!sCC_-_lYN4j->)S5ezhSjzvcNX(wIYWb2Uv1_GKgN+AfNxIx{8Lo?V>?y38D5)V$ zNfj*|g;OYVIywp?)i#~(ASaD0sht>GyMWX~sCwS=h9m_HhDq$xGBiW2-b1{(udI zo{jiZ8cpavC)J1zWHTP-rQGh7YBA7W?#}LWuVq{H@ijtPHU{WUk1UEAkHz-vELk0l zrFG-6L{i+WcI75{l|0UCae`-Q00ueN3kg+w5W}N8rcMj@(tYn>V5AsCDQR_i2#vQ; z0bI85U<=)vfEvBsLe=BZW+q$Z5uI?`+T`4T=J8UEr1^orI~R{OTe6Kp;*sFVHcE}h z=-jrQ?jfP}&~|ymcx65NN*3n!QW=`|rH@L`coU_e<$1O)%uSnwW>JoD$#0Ta&!QZAj|~VL zo0>Fj5)>J*j?yQIe%dv=Wk+(hjZYhzxDn@AiHZ~Y?`Z}{AniTiDy$}>X>yU4S1RkA zulcXtSlUvW+R|{SAT5+Vkw?Rk_CF43gjK<`e=_!jD^kflkq39a+_K9z?U>koT)lfr zuV4*-EuZ2bA*Ai2d5Ng>#(i`+QC>wPPr*HQk;kTpQ~y7f4%H9H{hV;bw8*pu-iiO? zjVFfW7flr-)xyMsk}jU62~HgMuBl!i_%PYb zgks|%Q5O>$9-c8!I@{wvQ0^wkTrLkt@phxRMO@(qpArn*dfo}>k{&@V$F!E2>s zs^U(Kp9yXC5{W0N0210%MdJ31XdlP4TSxU08N(AUZRtdc1fF;4TmmVnWT^DcZ%+D+7XJx&wov|p0puoiC$uwl56D} zp0@kcOV8=fP} zOJ#bAr*7>;-%jUwq42u5!aB((i7&RF8;<3*cm)#>zJFR@gK(fXa+ zo4I&Tf^AJO@bs)t|^dW9-X8z zR;=7fD@l|)C8d}Vr^qh_ij`}|Bng40q(HHrXj3+X)#`XZTa!HwBL>z?63AC#w)qU{ zKgz2~x;_Th}KIZl#dWp0ae?Wq3_hEj!hKW~JjMYngL)ME>eXGav>jjNP>HNpe#@F-$TEy^> z{=LuLWz~K2>gZzv9#hOB49DS+;AwF+cW~l%-1R`8(&hj*KY8oQQp)}p?G*imbuX#< z5-jwVypk6``wcQTh^II0lKiN&HdH=3p?T3tUhrP(v-M)$cXK4r%g|v!Grh!vkUAMbfa4Ivs~$HJ4)5Z%1+)%bRjj>bq2|tu~{P zOU1hX#3|cwLEda@D&A~&drc3P!cSmF@30I_82*}km%%?wcuk3Xzwk9JUncJ1_i6rV zcn*IuJx%s2cx!8}srdEWmNz64-k1LVMmfp}fBE@CYQ$ekh1f^El^e+8ZNaWHCa!}K z!-qVG+5VP>6G|_8OS6%OkpCy`Co$ThbhNzsn;*4w*TGw-`TSJboPR@Ymc!=b#Za&1 zNPxoUad_<=9bS%%lmiR=(P%O7pU>uWeNPwHi>5Ys$EoV`UiPF}i%gDAS52CPoS_LH z6%Bk($ty6UWI8O zM~>+@#j>O>2sG_K%2UF5@qmP*t26L6$rVrdw8j4;O-)BBkss;xHh#P4sEYkad(uTe zQ{A7!j9p%6oS5WCChD6X$#k`7Q(^U-RXxfmU^TLnx0t4Mag8V{ZCYD|=PRMtYeZ86 z?tz+=zZ#2wrEM)LZd_k=t?cEKv$XN zKd(3I;4riz%(-+FpdwFnyl_=TIhzr_R8iSxu{QRjxLUw5BP0oaqEtkP7sz29`itxM zAI+dt-i;&5R|bPgRdMxtsVD?P^S_H!MxF507_MNrI^g}JqKW}utH?GJL!^$OT5>H_ z7kBJgW9AJwy=Jid{I9tog=eB%C6OT~(p8dIm2xG`wP%q7FIL)_ZW~f>XRnE9Mr9{l zZf&KlH}d?X0FxyTFE&+e%IxBh3Iaa@Z=070f-}C8I3^wxS%_fOuEdSuYA% zi8DG`A9IWPFij@V_{GqPv#YpianQ&%jMJ;>Xci20gX(k#_DADUT`g@~-F}?k^P^c* zt}MtM-nTlLY^u;4exVA5Y(mM<%Vrx|!j(1Tt4gj)jSTU^(G?Gikejyrfe#7i@*74; ziwvcqDOLTeDME`ki<++|ua%3csD|8Y_sh;_H+88df384!`6*BEFXtEz&78Jid?<%z zl(7cy0t;t~2Hc_-w){&oIOuvro}d5M{=+XwNc|w2Qd6mo*4Cmm+_g%}E6V7+m10@{ zqme7}4ZL2Fe1jRrp{ojxBxV~vM*e<$g%X1p?D&xP4$or=VT7V1`A5>d(W*5X+YAdkJI0hR5o6QF<@qgsq zxb1Zir{a>$Zq45c{tsJSQFlwLnJ>C~+zuF#2l!e9PmVWrY3mMjI*iM`9in&T_Vv`# z(wM@hq4&MAu__F$N8#C6ZJyGor6W@3eLvlQvL-)DZ#QpfC_5X~8fl4NI!0zgtmqTp zkFlcKJK@9^TT#?bJl8oDSN_}-FWsaMUh$dU6GZk163l7J+~JvZ?Vd(TC!8i8)gi z%$63t)VhE4SK^Nh%&Bj9_R;G>O8mp3h~ytVqj!zPJzMmL*Lxleh+a@> z__VdOE>{e7tNWKcwDB2&u(VB8UpB`*zcn - - - - - - - - Account - - - {truncate(address, { start: 5, end: 5 })} - - - - - - - - - - { - setParams({ tab: item.value }) - }} - /> - - - - {/* - - */} + if (!address) return null + return ( + <> + + + + + + + + Account + + + {truncate(address, { start: 5, end: 10 })} + + + - - - - - ) + + + + + + { + setParams({ tab: item.value }) + }} + /> + + + + {/**/} + {/* */} + {/**/} + + + + + + ) } function Tokens({ accountAddress }: { accountAddress: Address }) { - const { tokens } = useAccountTokens({ address: accountAddress }) + const { tokens } = useAccountTokens({ address: accountAddress }) - if (!accountAddress) return null - return ( - - - - - - - - TOKEN - - - - - BALANCE - - - - - ACTIONS - - - - - - - - {/* Native ETH */} - - {/* TODO: Handle empty state. */} - {tokens?.map((token) => - token.visible ? ( - - ) : null, - )} - - ) + if (!accountAddress) return null + return ( + + + + + + + + TOKEN + + + + + BALANCE + + + + + ACTIONS + + + + + + + + {/* Native ETH */} + + {/* TODO: Handle empty state. */} + {tokens?.map((token) => + token.visible ? ( + + ) : null, + )} + + ) } function ImportToken({ accountAddress }: { accountAddress: Address }) { - const { addToken } = useAccountTokens({ address: accountAddress }) + const { addToken } = useAccountTokens({ address: accountAddress }) - const { handleSubmit, register, reset } = useForm<{ address: string }>({ - defaultValues: { - address: '', - }, - }) + const { handleSubmit, register, reset } = useForm<{ address: string }>({ + defaultValues: { + address: '', + }, + }) - const submit = handleSubmit(async ({ address }) => { - try { - if (!accountAddress || !address || !isAddress(address)) { - toast.error('Invalid token address') - reset() - return - } + const submit = handleSubmit(async ({ address }) => { + try { + if (!accountAddress || !address || !isAddress(address)) { + toast.error('Invalid token address') + reset() + return + } - addToken({ tokenAddress: address }) - } finally { - reset() - } - }) + addToken({ tokenAddress: address }) + } finally { + reset() + } + }) - return ( - - - - - - - ) + return ( + + + + + + + ) } -function NativeTokenRow({ accountAddress }: { accountAddress: Address }) { - const navigate = useNavigate() - const { data: balance } = useBalance({ address: accountAddress }) - - const decimals = 18 - const symbol = 'ETH' - const name = 'Ethereum' - - return ( - <> - - - - - - - - - - {symbol} - - - - {name} - - - Native Token - - - - - {typeof balance === 'bigint' && ( - - {formatBalance(balance, decimals)} - - )} - - - { - e.stopPropagation() - navigate(`/transfer/${accountAddress}`) - }} - /> - - - - - - - - - ) +interface TokenRowProps { + accountAddress: Address + tokenAddress?: Address } -function TokenRow({ - accountAddress, - tokenAddress, -}: { accountAddress: Address; tokenAddress: Address }) { - const navigate = useNavigate() - const { hideToken, removeToken } = useAccountTokens({ - address: accountAddress, - }) - - const { data: balance, error: balanceError } = useErc20Balance({ - address: accountAddress, - tokenAddress, - }) +function TokenRow({ accountAddress, tokenAddress }: TokenRowProps) { + const navigate = useNavigate() + const isNative = !tokenAddress - const { data, error: metadataError } = useErc20Metadata({ - tokenAddress, - }) + // Native token balance + const { data: nativeBalance } = useBalance({ + address: accountAddress, + enabled: isNative, + }) - useEffect(() => { - if (balanceError) { - toast.error((balanceError as BaseError).shortMessage) - removeToken({ tokenAddress }) - } - }, [balanceError, tokenAddress, removeToken]) + // ERC20 token balance and metadata + const { removeToken } = useAccountTokens({ + address: accountAddress, + }) - useEffect(() => { - if (metadataError) { - toast.error((metadataError as BaseError).shortMessage) - removeToken({ tokenAddress }) - } - }, [metadataError, tokenAddress, removeToken]) + const { data: erc20Balance, error: balanceError } = useErc20Balance({ + address: accountAddress, + tokenAddress: tokenAddress!, + enabled: !isNative, + }) - const isLoading = !data - const { name, symbol, decimals } = data || {} - - return ( - <> - - - - - - {isLoading ? ( - - - - Importing... - - - ) : ( - <> - - - - - {symbol || '???'} - - - - {name} - - - - {tokenAddress} - - - - )} - - - - {typeof balance === 'bigint' && typeof decimals === 'number' && ( - - )} - - - - { - e.stopPropagation() - navigate(`/transfer/${accountAddress}/${tokenAddress}`) - }} - /> - { - e.stopPropagation() - hideToken({ tokenAddress }) - }} - /> - - - - - - - - - - ) -} + const { data: metadata, error: metadataError } = useErc20Metadata({ + tokenAddress: tokenAddress!, + enabled: !isNative, + }) -function BalanceInput({ - address, - balance, - decimals, - tokenAddress, -}: { - address: Address - balance: bigint - decimals: number - tokenAddress: Address -}) { - const { mutate, isPending } = useSetErc20Balance() + // Error handling for ERC20 tokens + useEffect(() => { + if (!tokenAddress) return - const [value, setValue] = useState(formatBalance(balance, decimals)) + if (balanceError) { + toast.error((balanceError as BaseError).shortMessage) + removeToken({ tokenAddress }) + return + } + if (metadataError) { + toast.error((metadataError as BaseError).shortMessage) + removeToken({ tokenAddress }) + return + } + }, [metadataError, balanceError, tokenAddress, removeToken]) - useEffect(() => { - setValue(formatBalance(balance, decimals)) - }, [balance, decimals]) + // Derived values + const balance = isNative ? nativeBalance : erc20Balance + const decimals = isNative ? 18 : metadata?.decimals ?? 0 + const symbol = isNative ? 'ETH' : metadata?.symbol ?? '???' + const name = isNative ? 'Ethereum' : metadata?.name ?? 'Token' + const isLoading = !isNative && !metadata - return ( - - - {isPending && ( - - - - )} - - setValue(e.target.value)} - onClick={(e) => e.stopPropagation()} - onBlur={(e) => { - const newValue = parseUnits( - e.target.value as `${number}`, - decimals, - ) - if (newValue !== balance) { - mutate({ - address, - tokenAddress, - value: newValue, - }) - } - }} - height="24px" - style={{ maxWidth: '180px', textAlign: 'right' }} - value={value} - /> - - - - ) + return ( + <> + + + + + + {isLoading ? ( + + + + Importing... + + + ) : ( + <> + + + {symbol} + + + {isNative ? ( + + + Gas token + + + ) : ( + + + + {truncate(tokenAddress!, { start: 4, end: 3 })} + + + + + )} + + )} + + + + + {formatBalance(balance ?? 0n, decimals)} + + + + { + e.stopPropagation() + navigate( + tokenAddress + ? `/transfer/${accountAddress}/${tokenAddress}` + : `/transfer/${accountAddress}` + ) + }} + /> + + + + + + + + + ) } + diff --git a/src/screens/index.tsx b/src/screens/index.tsx index d81dd14..c6bbd97 100644 --- a/src/screens/index.tsx +++ b/src/screens/index.tsx @@ -79,7 +79,7 @@ export default function Index() { items={[ { label: 'Accounts', value: 'accounts' }, { label: 'Contracts', value: 'contracts' }, - { label: 'Transactions', value: 'transactions' }, + { label: 'TXs', value: 'txs' }, { label: 'Blocks', value: 'blocks' }, ]} onSelect={(item) => { From 2df608235de8d1313411efc57baa74eeca7415e1 Mon Sep 17 00:00:00 2001 From: "Petros G. Sideris" Date: Sat, 8 Nov 2025 00:02:15 +0000 Subject: [PATCH 4/5] Update error msg on send --- src/screens/account-details.tsx | 549 ++++++++++++++++---------------- src/screens/token-transfer.tsx | 29 +- 2 files changed, 295 insertions(+), 283 deletions(-) diff --git a/src/screens/account-details.tsx b/src/screens/account-details.tsx index 1f4cc00..32bea7b 100644 --- a/src/screens/account-details.tsx +++ b/src/screens/account-details.tsx @@ -3,12 +3,7 @@ import { useEffect } from 'react' import { useForm } from 'react-hook-form' import { useNavigate, useParams, useSearchParams } from 'react-router-dom' import { toast } from 'sonner' -import { - type Address, - type BaseError, - formatUnits, - isAddress, -} from 'viem' +import { type Address, type BaseError, formatUnits, isAddress } from 'viem' import { TabsContent, TabsList, Tooltip } from '~/components' import * as Form from '~/components/form' @@ -16,28 +11,28 @@ import { Spinner } from '~/components/svgs' import { truncate } from '~/utils' function formatBalance( - balance: bigint, - decimals: number, - maxDecimals = 5, + balance: bigint, + decimals: number, + maxDecimals = 5, ): string { - const formatted = formatUnits(balance, decimals) - const [whole, decimal] = formatted.split('.') - if (!decimal) return whole - const truncated = decimal.slice(0, maxDecimals) - const trimmed = truncated.replace(/0+$/, '') - return trimmed ? `${whole}.${trimmed}` : whole + const formatted = formatUnits(balance, decimals) + const [whole, decimal] = formatted.split('.') + if (!decimal) return whole + const truncated = decimal.slice(0, maxDecimals) + const trimmed = truncated.replace(/0+$/, '') + return trimmed ? `${whole}.${trimmed}` : whole } import { - Bleed, - Box, - Button, - Column, - Columns, - Inline, - Inset, - Separator, - Stack, - Text, + Bleed, + Box, + Button, + Column, + Columns, + Inline, + Inset, + Separator, + Stack, + Text, } from '~/design-system' import { useAccountTokens } from '~/hooks/useAccountTokens' import { useBalance } from '~/hooks/useBalance' @@ -45,285 +40,281 @@ import { useErc20Balance } from '~/hooks/useErc20Balance' import { useErc20Metadata } from '~/hooks/useErc20Metadata' export default function AccountDetails() { - const { address } = useParams() - const [params, setParams] = useSearchParams({ tab: 'tokens' }) - const navigate = useNavigate() + const { address } = useParams() + const [params, setParams] = useSearchParams({ tab: 'tokens' }) + const navigate = useNavigate() - if (!address) return null - return ( - <> - - - - - - - - Account - - - {truncate(address, { start: 5, end: 10 })} - - - + if (!address) return null + return ( + <> + + + + + + + + Account + + + {truncate(address, { start: 5, end: 10 })} + + + + + + + + + + { + setParams({ tab: item.value }) + }} + /> + + + + {/**/} + {/* */} + {/**/} - - - - - - { - setParams({ tab: item.value }) - }} - /> - - - - {/**/} - {/* */} - {/**/} - - - - - - ) + + + + + ) } function Tokens({ accountAddress }: { accountAddress: Address }) { - const { tokens } = useAccountTokens({ address: accountAddress }) + const { tokens } = useAccountTokens({ address: accountAddress }) - if (!accountAddress) return null - return ( - - - - - - - - TOKEN - - - - - BALANCE - - - - - ACTIONS - - - - - - - - {/* Native ETH */} - - {/* TODO: Handle empty state. */} - {tokens?.map((token) => - token.visible ? ( - - ) : null, - )} - - ) + if (!accountAddress) return null + return ( + + + + + + + + TOKEN + + + + + BALANCE + + + + + ACTIONS + + + + + + + + {/* Native ETH */} + + {/* TODO: Handle empty state. */} + {tokens?.map((token) => + token.visible ? ( + + ) : null, + )} + + ) } function ImportToken({ accountAddress }: { accountAddress: Address }) { - const { addToken } = useAccountTokens({ address: accountAddress }) + const { addToken } = useAccountTokens({ address: accountAddress }) - const { handleSubmit, register, reset } = useForm<{ address: string }>({ - defaultValues: { - address: '', - }, - }) + const { handleSubmit, register, reset } = useForm<{ address: string }>({ + defaultValues: { + address: '', + }, + }) - const submit = handleSubmit(async ({ address }) => { - try { - if (!accountAddress || !address || !isAddress(address)) { - toast.error('Invalid token address') - reset() - return - } + const submit = handleSubmit(async ({ address }) => { + try { + if (!accountAddress || !address || !isAddress(address)) { + toast.error('Invalid token address') + reset() + return + } - addToken({ tokenAddress: address }) - } finally { - reset() - } - }) + addToken({ tokenAddress: address }) + } finally { + reset() + } + }) - return ( - - - - - - - ) + return ( + + + + + + + ) } interface TokenRowProps { - accountAddress: Address - tokenAddress?: Address + accountAddress: Address + tokenAddress?: Address } function TokenRow({ accountAddress, tokenAddress }: TokenRowProps) { - const navigate = useNavigate() - const isNative = !tokenAddress + const navigate = useNavigate() + const isNative = !tokenAddress - // Native token balance - const { data: nativeBalance } = useBalance({ - address: accountAddress, - enabled: isNative, - }) + const { data: nativeBalance } = useBalance({ + address: accountAddress, + }) - // ERC20 token balance and metadata - const { removeToken } = useAccountTokens({ - address: accountAddress, - }) + const { removeToken } = useAccountTokens({ + address: accountAddress, + }) - const { data: erc20Balance, error: balanceError } = useErc20Balance({ - address: accountAddress, - tokenAddress: tokenAddress!, - enabled: !isNative, - }) + const { data: erc20Balance, error: balanceError } = useErc20Balance({ + address: accountAddress, + tokenAddress: tokenAddress!, + }) - const { data: metadata, error: metadataError } = useErc20Metadata({ - tokenAddress: tokenAddress!, - enabled: !isNative, - }) + const { data: metadata, error: metadataError } = useErc20Metadata({ + tokenAddress: tokenAddress!, + }) - // Error handling for ERC20 tokens - useEffect(() => { - if (!tokenAddress) return + useEffect(() => { + if (!tokenAddress) return - if (balanceError) { - toast.error((balanceError as BaseError).shortMessage) - removeToken({ tokenAddress }) - return - } - if (metadataError) { - toast.error((metadataError as BaseError).shortMessage) - removeToken({ tokenAddress }) - return - } - }, [metadataError, balanceError, tokenAddress, removeToken]) + if (balanceError) { + toast.error((balanceError as BaseError).shortMessage) + removeToken({ tokenAddress }) + return + } + if (metadataError) { + toast.error((metadataError as BaseError).shortMessage) + removeToken({ tokenAddress }) + return + } + }, [metadataError, balanceError, tokenAddress, removeToken]) - // Derived values - const balance = isNative ? nativeBalance : erc20Balance - const decimals = isNative ? 18 : metadata?.decimals ?? 0 - const symbol = isNative ? 'ETH' : metadata?.symbol ?? '???' - const name = isNative ? 'Ethereum' : metadata?.name ?? 'Token' - const isLoading = !isNative && !metadata + const balance = isNative ? nativeBalance : erc20Balance + const decimals = isNative ? 18 : metadata?.decimals ?? 0 + const symbol = isNative ? 'ETH' : metadata?.symbol ?? '???' + const name = isNative ? 'Ethereum' : metadata?.name ?? 'Token' + const isLoading = !isNative && !metadata - return ( - <> - - - - - - {isLoading ? ( - - - - Importing... - - - ) : ( - <> - - - {symbol} - - - {isNative ? ( - - - Gas token - - - ) : ( - - - - {truncate(tokenAddress!, { start: 4, end: 3 })} - - - - - )} - - )} - - - - - {formatBalance(balance ?? 0n, decimals)} - - - - { - e.stopPropagation() - navigate( - tokenAddress - ? `/transfer/${accountAddress}/${tokenAddress}` - : `/transfer/${accountAddress}` - ) - }} - /> - - - - - - - - - ) + return ( + <> + + + + + + {isLoading ? ( + + + + Importing... + + + ) : ( + <> + + + {symbol} + + + {isNative ? ( + + + Gas token + + + ) : ( + + + + {truncate(tokenAddress!, { start: 4, end: 3 })} + + + + + )} + + )} + + + + + {formatBalance(balance ?? 0n, decimals)} + + + + { + e.stopPropagation() + navigate( + tokenAddress + ? `/transfer/${accountAddress}/${tokenAddress}` + : `/transfer/${accountAddress}`, + ) + }} + /> + + + + + + + + + ) } - diff --git a/src/screens/token-transfer.tsx b/src/screens/token-transfer.tsx index 4244781..3482fc8 100644 --- a/src/screens/token-transfer.tsx +++ b/src/screens/token-transfer.tsx @@ -5,6 +5,7 @@ import { toast } from 'sonner' import { type Address, type BaseError, + type Hex, formatUnits, isAddress, parseUnits, @@ -86,7 +87,7 @@ export default function TokenTransfer() { try { const amount = parseUnits(data.amount, decimals) - let txHash: string + let txHash: Hex if (isNativeTransfer) { // Native ETH transfer @@ -107,11 +108,31 @@ export default function TokenTransfer() { }) } - toast.success(`Transfer successful! TX: ${txHash.slice(0, 10)}...`) - navigate(-1) + // Wait for transaction receipt to confirm success/failure + const receipt = await client.waitForTransactionReceipt({ hash: txHash }) + + if (receipt.status === 'success') { + toast.success(`Transfer successful! TX: ${txHash.slice(0, 10)}...`) + navigate(-1) + } else { + toast.error('Transaction reverted') + } } catch (error) { const err = error as BaseError - toast.error(err.shortMessage || 'Transfer failed') + console.error('Transfer error:', err) + + // Show detailed error message including cause if available + const errorMessage = + err.shortMessage || + (err.cause as any)?.reason || + (err.cause as any)?.shortMessage || + err.message || + 'Transfer failed' + + toast.error(errorMessage, { + description: (err.cause as any)?.details || err.details, + duration: 5000, + }) } finally { setIsSubmitting(false) } From 888983879960687bebcc684b49c2bd843713db13 Mon Sep 17 00:00:00 2001 From: "Petros G. Sideris" Date: Sat, 8 Nov 2025 00:06:12 +0000 Subject: [PATCH 5/5] Add yarn --- bun.lockb | Bin 383106 -> 383106 bytes yarn.lock | 57 ++++++++++++++++++++++++++++++++++++------------------ 2 files changed, 38 insertions(+), 19 deletions(-) diff --git a/bun.lockb b/bun.lockb index f8de0c7852ea746dbef20a2b10b626f52bf98f02..a6adfbaa1f9684d41e2d1624ce3f1fa461698a98 100755 GIT binary patch delta 52 zcmZqLDBiSDyrG4$g{g&k3rjp3qv7@hHkOY}j27F2I9WQF7|o{N=4RQ>Xx2WNhh_U@ I9@h7#0kxeI9WQF7)__&=4RQ>Xxu)Thh_U@ I9@h7#0kt_0!T