From c56eaf55d860d722f69b2de38bce616afd0ffa32 Mon Sep 17 00:00:00 2001 From: Ziad Saab Date: Wed, 31 Jul 2024 12:25:04 -0500 Subject: [PATCH] Translate Custom UI examples to JSX (#1348) * Translate Custom UI examples to JSX * Add flaskOnly prop for TabItem * Import Tabs and TabItem components * Add Dropdown JSX component * Adjust description of JSX Link * .js > .tsx * .tsx > .jsx * Add Field component docs * Update snaps/features/custom-ui/with-jsx.md Co-authored-by: Maarten Zuidhoorn * JSX is not flask-only, functions is deprecated * document JSX Box props * edit custom ui with jsx * update what's new * Replace single-quote imports with double quotes * Add notes for version 12+ And fix link to tx insights feature --------- Co-authored-by: Christian Montoya Co-authored-by: Maarten Zuidhoorn Co-authored-by: Alexandra Tran Co-authored-by: Alexandra Carrillo <12214231+alexandratran@users.noreply.github.com> --- docs/whats-new.md | 2 + services/index.md | 6 +- snaps/assets/custom-ui-box.png | Bin 0 -> 28540 bytes snaps/assets/custom-ui-dropdown-active.png | Bin 0 -> 50559 bytes snaps/assets/custom-ui-dropdown.png | Bin 0 -> 25363 bytes snaps/assets/custom-ui-field.png | Bin 0 -> 37228 bytes snaps/features/cron-jobs.md | 43 +- snaps/features/custom-ui/dialogs.md | 91 +++ snaps/features/custom-ui/home-pages.md | 28 + snaps/features/custom-ui/index.md | 9 +- snaps/features/custom-ui/interactive-ui.md | 8 + snaps/features/custom-ui/with-jsx.md | 687 ++++++++++++++++++ snaps/features/lifecycle-hooks.md | 66 ++ snaps/features/signature-insights.md | 33 + snaps/features/transaction-insights.md | 72 ++ snaps/get-started/quickstart.md | 51 +- snaps/how-to/use-environment-variables.md | 60 +- snaps/learn/tutorials/gas-estimation.md | 54 +- snaps/learn/tutorials/transaction-insights.md | 82 +++ snaps/reference/entry-points.md | 138 ++-- snaps/reference/snaps-api.md | 69 +- src/theme/Tabs/index.tsx | 177 +++++ src/theme/Tabs/styles.module.css | 27 + wallet/how-to/use-sdk/gaming/unity/index.md | 2 +- 24 files changed, 1604 insertions(+), 101 deletions(-) create mode 100644 snaps/assets/custom-ui-box.png create mode 100644 snaps/assets/custom-ui-dropdown-active.png create mode 100644 snaps/assets/custom-ui-dropdown.png create mode 100644 snaps/assets/custom-ui-field.png create mode 100644 snaps/features/custom-ui/with-jsx.md create mode 100644 src/theme/Tabs/index.tsx create mode 100644 src/theme/Tabs/styles.module.css diff --git a/docs/whats-new.md b/docs/whats-new.md index 97e92cec550..d14746b29a6 100644 --- a/docs/whats-new.md +++ b/docs/whats-new.md @@ -19,6 +19,8 @@ of the [MetaMask developer page](https://metamask.io/developer/). ## June 2024 +- Documented [Snaps custom UI with JSX](/snaps/features/custom-ui/with-jsx). + ([#1348](https://github.com/MetaMask/metamask-docs/pull/1348)) - Updated [React dapp with global state tutorial](/wallet/tutorials/react-dapp-global-state) with instructions for EIP-6963. ([#1330](https://github.com/MetaMask/metamask-docs/pull/1330)) diff --git a/services/index.md b/services/index.md index 5c6c9f4541a..bacbc387883 100644 --- a/services/index.md +++ b/services/index.md @@ -3,9 +3,9 @@ sidebar_label: Introduction sidebar_position: 1 --- -import CodeTerminal from '@site/src/components/CodeTerminal/CodeTerminal.jsx'; -import SectionAPIs from '@site/src/components/Sections/SectionAPIs.jsx'; -import SectionNetworks from '@site/src/components/Sections/SectionNetworks.jsx'; +import CodeTerminal from "@site/src/components/CodeTerminal/CodeTerminal.jsx"; +import SectionAPIs from "@site/src/components/Sections/SectionAPIs.jsx"; +import SectionNetworks from "@site/src/components/Sections/SectionNetworks.jsx"; # Build and scale your dapp using services diff --git a/snaps/assets/custom-ui-box.png b/snaps/assets/custom-ui-box.png new file mode 100644 index 0000000000000000000000000000000000000000..11e9b04de19a55939af1d542c013687a6a75123b GIT binary patch literal 28540 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 literal 0 HcmV?d00001 diff --git a/snaps/assets/custom-ui-dropdown-active.png b/snaps/assets/custom-ui-dropdown-active.png new file mode 100644 index 0000000000000000000000000000000000000000..6db3a940bc24fd26b3eef288a16ffab7ad27e532 GIT binary patch literal 50559 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

74a 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 literal 0 HcmV?d00001 diff --git a/snaps/assets/custom-ui-dropdown.png b/snaps/assets/custom-ui-dropdown.png new file mode 100644 index 0000000000000000000000000000000000000000..2f0bb094bf91ef40990c18c84af13c98fbb9059b GIT binary patch literal 25363 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 Td@KWMf%|S~>Rv6nf(-s2=>ra( literal 0 HcmV?d00001 diff --git a/snaps/assets/custom-ui-field.png b/snaps/assets/custom-ui-field.png new file mode 100644 index 0000000000000000000000000000000000000000..0ad7cd9400d4485efc68f420df6a5019ecc91092 GIT binary patch literal 37228 zcmeFYbyQqS(>IC+O|W3W-Q696JHg!F(<8s;;)G-;PvKl75Z+4jBpx>b0zlgenvi3>XRuIuG#`B<2DX zUjYS$DrzMzt|BWgPO9SU0I;&PfP#{VOx8lsRvX00)=P{R{Rj6>xXCBBDMex}uiuAy+p>07}?K^|(=u4Zsh6`l3l_POwL+3kAC zycE1{+TS#sb0Jje}^YCS`>Jp`>8wS>fLi+E+&4V`INE#*SsPC|5nZCDt31E6B=+BG`MTxwjZph4oumKCTHm#q)iw2dK!~@KxNi@|CO2K=D zcxFncl)7n6rL)2-1`T4%L94vM)fuK{a*w7vbn_mjrC80I^D1Ajidv0_cUAZ$6QXB&GVB zc|?d=flHWITQV1y`ezN&6RaXBiTCA5X9&>B05mqa!FV{(@bL#&duEg!)IHIofz8|S z_qI?@xvT=@3f;v;NHFv0z1YE{=vy_Lq%)zOY$80QnkIF!f?QJTD0T{1b!o`Ygwl)` z3|Cj8iP&T6dtIYzb=dc5)?!lnS13p4u6^O z906h5kIaId0fD|J+Gs|2BxOJENQW+>65{&k@{VXjh3tpM-XxwEp$qKpfav=-kh~nl zhOW*yKNzZK3M#dee!;?|ibF7h?twzNh2@X`o`GBxtU$WAXLAtZah@&u9ojVh&Fy!? zZqyi=q$|XAE}XZ4B4isOOY2VlwT8k2;g7Q>n*I$4R<$d>^AU`{-fj@0BiF8XNN~&X z9x*`+21T!ttngJko3zhY%RRgZiTv=lOp8ZSV@)KBb8R4#H-#F{!Baq`Tv)qr<~fNB z?=E90SK@{BAjtrE`1Gi~r&-5X=l>ez=<_*O?F9Z8tc_9GUjixMaBJEC@zlC9LRC_f>p<$1Zm427MPq-9A_e_ z@hrluOz3!jqphkcp7Gk#S9z1qS$ek!P=+7`1O&8z-S@Gu)w8edU&L4WY+gOO(!x5P zplgwjrn)p=z7KRj;%c6}48&lCopBUa`i|`hV}uU%UX(HdR@Rt3S{Sy{g)Qw3AOt=a zFDV$?_;m>!K{rk{?9rBiT1ux2I++UzM|ku@#aNSd+J##h=XzN1<-%;jhg5m-*|lt9Pp$Zz^LotTAR=R~pe zF`N;3Qmlj-^^t5m-SWUB8;e#`c%sjJI{W0>JM#)0sK-Cn_lF&AoL-+12!)IKo z*hEUSE+EW*d$&)MrlHRjk;NJzgG;gVq#GtAdp(Q zPR1o_hi(MK84Zv!8*i=;t*@w`thZ;%OG(DjV^Awow`tN0*X(L6YOHe)zD7N!Kh9q; z;7^M!e4|IBXW23;oJGK&BZU`h9J>~$&7SA~BN^k=P5R*e;M`5#mB6*?(0?NT5Pr{M zzhcT}qOB_KaPdI;PrFpZ2WAAI%`$45YQB3moH=doy4vx7$yTh&Z5n@2L{$h@q@)Ha z@+$}fb<_KSI2qh&D?IsWY~Ts7Ca@vn3P=D92aa)9ader9H5zN1YnM0h+MKOS46%

f&U@=4gVXHH=%D7->^snxi28 zSBUcYsLd7D(^A-~vTU=Ol{A!Q`&B`&VzYP}y^a_x1uQ!+UhV2JbEZ0`N-|e48yPI? z_f=k1cG&OO)7ekk^Wf`7)Apc{WQks~R;^kN(c6izq!}51ti%L(J8T+!R)}uiWc?c>$(6rn9%>o4e6n zX$3iyGS*7eR5X+h^2BNAtR^F$P9mAHqG(pq%(<-k3ogD~(O4=A^Gn(xTMj+HeJ^J^ zG@8VcDWmk-k~BF>H)~b@*^01^ka^dfXg7*5bYaVbEy;?-c6T7n3Z^;E`mNgqtgdSTQ2IVa9x}|?m0FPFmg>gpt;`S9HSWqIW4 z8ZsJP-^tws3MC4S-4q>l)Udc39s2h_-^1b{d_$Xflfp?J!$I%>WY1{L_>v)j7D{Ms zcV^4yIk*1nnu1#TTdXySfq%4f`QF^xS@0$-jReiTQc;fY5`W>KwXSzXa@FEZ^NA-pHMlt+E6d z|H|D#1B$$B)o+Uxz6_XqroA3t1}%YDvbTiqCJZi9m|sIAl*9+<2p5FCxtde;+Ejbj7Y*=ndU&Rqw_?M!Au}qO4PcA40-$vJVuZ=$X`&vu#E|o)$6rU}$WdVwc zQ1p;6A`~3-J1BTa2paMTLlgWHmV%~*g8eHV1_~Vl*wy>~w`RL&K#LwOdi9m9c(Q$!- z!lC;8K+CF9{(_W0W2LU`s;#KNZ{}dfY+~+UYQgMj=lHuEC_zttNYKv0)r8d3&eqV8g^iDokA;<;g`J%Vl7q>`%ih(*lgZwN;y;D_U5 ziO+^`CZHcv}6b$=>C^Y(W@g`JKYT#>~p{PuUPs z!QZj`DpsBrwmK44b`Y6C>Ja8+;}!fX|NkT9PmTYg)c!-s!^Zt@%73N&-;^3I7S7@h zc91Gvh5vNde~JH{_+LUnmfxKJOA`MP^Ix$LISV5Tvi#F$!pP_rI)spJB(#!HR)@SH zO7_<^4*8{pJip(NN1@!)t=Jw4N)$>~LQLHg`X~!&344+Nl=F5$B9S|xKEakrmr>`r zQKq&5anLZbq#!Ata-JSjH@Tx+R)?JGIH6GJ_`?EjQ<>dEQt zN5JTLrc0;GPDdBt1vuT;=lW<6lfm2~lu(y$zU{1tAY}X~&3CRpahBQgl%^-lF7AO+ z6z0Eo{65_I_Ao9_u(s{(2mzB(`TpHfFn&iYHFJL9LygJaeT~I=hFv^+k!`abyKPum z)Y-piaS*^BGGiBNgbl1x(U4%D~Xgz7sEVZv|Oga0)qMuzIjK6$N!TGes7GXMQGjwYg zo+XmROJajxsW5J^rLfdPt9#Kqr;`FqDWILHpBQ*vlaTJeF5Z7w`<>y$s%1`Di@IP(Fyyz8v^0- zFd`%crRuP4yxZMCy22@sC+&QY+H4tNAnb`90ohON;=Px-C-!ee50&|AEcE`XI;2$? zj!}*6GyWbvSmQaQ+@^F`%nsV!(MtXFYo;S41#ftKZ=B+}o9%w3{i#fblsCw+hohvA z^xBjOi!ML{k{=!;S8NEbVwmMN*Y4aV=k6cXlp&o&l)y|st3|XHkZJj7k%tUus}qy3 zjAuWau}Y1z6j^BmsqqXa{uu@IND^2vgSPVRZU}TF^66=C9HQ{p31Y)7%1U`h&BsL> zyev&Z*uL5be~+8M0GJv?;TKJ{FB~82(5z`@obR5W9~@Q>Sr-vQK6mAAAGIDoNi5dc zx#awt34fRxQOU z!~`2dk{X5~V`Q?0)RaR8UoB^zx+kn=+Y)$i|5zXC^)Jqekmg|6v5(~?{KRZMlh59Q zU%gim!>`XQ#a)z`t3IZ(7BN^%E_oh*^EW5ogOtC^zbz84!Wys4M~#L4EQg+qpSF1m8 zMQ+RqvnC^7mxAfV8Up+IR4=PD?+tQU;| zYnCTY+syJw#xeSTYJH$(4#yQxK*px0MZl#+zhNhjbvpU)y#JT#7kq-^Tw8s(9z0q0 zF+XfP9*Q!qdu;KFQoCWZ7?$Zn-p(?s%981sVF;+_6}k3B0;s=L+>)}1)@og(1|;J$ z8&V6npG?gU(|rV`Fi?cTF4=ibgLwa_FKN&vdA0n0SF+8_V8#ozd=w5Hxdww4m~HV$ zdai$gql?=Q1<(d<|J9}#ei>xYA8dp}_p;^ZtUaFh?kyk*|BqS+!oBf@`5BzXyWD9O ze(u6dN|U24>4Qtzy6Z1lYv4fIZA&2Y$#bQ}CKdc}hRc*9pDZZ%jX_k5->fO>e=GoA zQBbbi%GNM$y(9z;AB8LWBdv>C9G9{pw6yw}(iG7)Fh*T=SX4Z)1mI2Yw!VCO_hsqN zGy#QVP8tL+!ZMY2SDh!h6|JWHMuF7ut1Z1!nlbmQnixqz7QGr(O}Z}ZW|Jx5&9|eB zi=-|8(h7VTC|&2BOp18C#$N&PHLWX5Qq3`1wS$kPs{5W;S(tHfdJ*A}$pu+&Dx+D# z;S9cuZgoTzP*-4h%+c(sp9eij{HF<9PB7ZeCvE92>MZAj^HT2gJU7dE<7Wd)r2#T2a)`C`5^?_QE&+uKyen`r@2KQ@spgCZO6;@Ob)c z{)J>wGz%IY;w2-h#k=@bjw2V64!5 zaLdQ;N7ePc9@QFklTt&&ZsB!Dx&ZaB-`#3R|A;DH)Ee>V>A@kL-7bu3D92X(ofx~ib|dVuEj82_Y)_y)$ni5w<9q2U%lp#* z$C?EX*Lmyxt+H@k$BkkpMFyg-Nu1rbTETuzfw9u8%1>@}?Q9km3P$zw28y|xts0-@ zFY1QnLah5>lP$^qJsE6aAkw6Lp^9G?l1(>mWC-(oL!U;&GDj&+U6CYdbRag-ms5! zX?3m0=*RK=c)?QZd*^(&yBbhvolLLVV4Zwv$EcU$4)=V2$dZ13tj_m!_G&S z;r`kpqzCi%>1Ng9?(=Ga7ul28M@itj&EAexFK1EP&=aO5=&RckvXkFYmzU=o%}9u)yd=SCd_<0ANT6h zq_T+O8-b&0!Rc*{GR@&5J{R-tp=9TuVt3m~YSsgEa=!?jBn~tiyh;{(&rf{JxSHsU z0_Y0ml7}?HAV;PId=9|9wfNKhRY9PxKiy<+8qZ3Sw6_p7!q8RD{_dBjF}Vfa$au^L1GBhjqa4;BoqUPPLt<4%*+ILH12eC1_V(>1DH;b-%9!KF=%`IgDW zvDWvY$j+eSCb`M73>DrsWfhoMgbrTq>;RKMGb9dqgtCUtRlqT7biupB zw2YUDDA?`bi?OIu1$&DX$g+Rw)7phfAUsir#8YoehURvhh{-m$5k_D!Q$F8HblQFu zmg#*!mu)Afv9;iKSg`Jed;iUTC;D{jmua8xwop9B2Ud~+%T&K%PMA_0u)WAWA%qp^ z!M6}rc4(3r`rB43>VP=40S}U(1D);o0a}FdPZwNQLjxg0Toft4K>ab^+-4I6W8$Ap z++l-X*8$v{FB78*Z#LuPK3r{QETK+z<&a^~C?#(6#l>GAFYEx+GFw-@ABc3C9TPH( z0Gk9xPAyocmbQ;9~Bq9%HcAHF)3aq%_zi7^_*l zJ5w}`Qxc{{ffPGu9NYsu@HW_n=Vp3&3A@AID8L`B5 zwf#`fF?*=RY_Jd5CQR>#Qt9fmXG!;lhQf#+a=CBQ_R_IO>`o}}|>ZyHEseA70k6M-bvP%4C63R`9RPrf9 zMItX#b;lqgpYn3OCc~YVUm@i>byD=2<+R0gIX^f0ZUPtqi;c(U!vQQZ!qcZ#%l_c+ zO)Z5D_Fv9hQWqMmy@cQKJW2O!@~o6!GY=|!90?a&`;=Juj_$>CKS!I}yZyI)?J&lmLYBrpDV+#ui2v7lI7(e6$JYxvX zLaiWAwAa2r)F*HrwB9reggX6SFwVx7#WTd&>q9idaZ zrXWw(tA|MVL+8uQ@~W(K*EfCUU_`TKNhVDQvqp2Re6ezP>LPTP{Qb9mT#u7uBEu&JZQJ#e%E{ImWd~gv+ChM}cU>StHKn0srn2G99LXr$ zvQ*V3-dVwZaCAC{#cZX)M6SQz)7xS5{;LMhLChy|ilqsq4*~h@{gNsxC7?Lt*lmXl zD}g4+8dypbkJwFECe!GHpK9Fr+C&5g`dEv#3I8$#Y*aI1kSrV~@Crt=>(^lh^w;Qg z3pfrABKxaoHHNoeW*4La#zFprwnskJfO79Wa9Sl}SisumT+49CC~CdITV~`e;=MHS z+yxO-B%jZbR5jZc$*QjCkn)sKN;#(9>gb&$(e$@s+XU?<`-jUysG> z^E+IlgJPmpI**uOlgAcdL$g?$K;Wd7k%B6ZjXaT(=lb#f^O$Gt-h6&r{l^vX#VZ*3 zdp8XRMN!&T*vFeTj{un?0?{S??-fYU{zJ`Py^5JRP-54vFP89iO(#$ULOz0wsrv1! zq20n->-|A~it`NRb7vt&gp_vnZOcwI>~8r=%}GSq{$vQ&Ue*J#%Dd z$|lz`x^@nVhQeDv#-{R+Wf=KcR6m}9q@I#q&!!WtG59M#xRY(tAv%~%GTY>c7a-gL z0Y}dAkW;ibj2N7YAk6%7?6E5no})>Sinty7gF2*^GEe!k;K zpVw%o7X>$-#ar?jz<0FjrKQ*L3E$t9TIu$OI{rri(=FQlrypOGbmkb{TxE5BO^%Iz zBS7amjq}rjph$4BcEY>qO5Eu+_{D~jn3>S?q?*O{43;nH{ajp5ym0r97Mo5TCrlRM z5KrsgP2qxb*DdNCI@9yMkiI&YEi1Mp>&oIEp?i=S3vcjb-;Ocn2F+!E1$*#mLKEzz7NZM z?x)t2!mfXJIaYZ)4r<_-LSb6 zPa}jD-AEQa?L+X4h-b#c<$;a3;kQ1;*Klo5wQEra20B?8f6pEF$gp*f*#fBTZ?nm>S73clJ)VV?Lu0U_hK-_4> z>c!7a2yCANJ(wN8d@5E!Bni0eR4>)nIaLN;XD#^-S9p`W7^9j&)>saEb85CsWA6RA zjivldj8&e-Rx!X>c0MR*JwsTjro#p&lT_fM_z9$jBjOo_) z)h!KU1x$L?ND@B=JjjdiIvIv4w6+mX9n(xz1ZZk*f1|N*JDHePzOMF~+ElPZXk>O+ zqLgnD=JiUBlA5s*59iyLi{`hQ!x!3lP4jwt8pTEF{{HH)ZdCY2Fe|pPwYOwe`mp|j zrF|f)Aa2$BkO*{*0{hCM)Gap47s%r<+Ik$@mU%gCGs9~&wEZJ8-0pG=jw&syUMY)& zbA0sr#QkRPl32)x&&l6INg%(GS-^hjf$uXdE_Sh@PU3mc!hqF5%MTrHcMHerCo0gF+04dK!WQ zyKJnBIDZiL69u;goHzvv?qu|MHHJj;xNY2v8BmuH#K*J2X}U+acg%Yo`*BemT~1CN zuLOq*yqsY)f=M%)lDipd) z8l(v+lp1qirN>I=5lOK2t_;gDE^gq065b02<8O>VB9=(^Bz%j^07#JknCg!K3SN{+ ze^v6cb{`lt^T+#%6QS#&!a~KrZF&a{`pyaSR>aXz><)_Gi}X>UIzX`N!M-)py>UdZ zal$S*-UXqTJUzH&P-B*NV`%E-{?Lq2$+~DnBHY$;G;@2aMzV&fXJN@*S_YpmSC~Un zC5|ZRwBie3vHs%IVjOkaG=e_iqEV@zK)G(ikZi~tXZOkQNQDE}IGNsd-7%v0

;b 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 literal 0 HcmV?d00001 diff --git a/snaps/features/cron-jobs.md b/snaps/features/cron-jobs.md index cc87cf056e3..92b4c32bc32 100644 --- a/snaps/features/cron-jobs.md +++ b/snaps/features/cron-jobs.md @@ -3,6 +3,9 @@ description: Schedule periodic actions for your users. sidebar_position: 1 --- +import Tabs from "@theme/Tabs"; +import TabItem from "@theme/TabItem"; + # Cron jobs You can schedule actions to run periodically at fixed times or intervals, also known as "cron jobs." @@ -40,8 +43,43 @@ Expose an [`onCronjob`](../reference/entry-points.md#oncronjob) entry point, whi the specified schedule with the requests defined in the `endowment:cronjob` permission. The following example handles the `execute` method specified in the previous example: + + + + +```tsx title="index.tsx" +import type { OnCronjobHandler } from "@metamask/snaps-sdk"; +import { Box, Heading, Text } from "@metamask/snaps-sdk/jsx"; + +export const onCronjob: OnCronjobHandler = async ({ request }) => { + switch (request.method) { + case "execute": + // Cron jobs can execute any method that is available to the Snap. + return snap.request({ + method: "snap_dialog", + params: { + type: "alert", + content: ( + + Cron job + This dialog was triggered by a cron job. + + ), + }, + }); + + default: + throw new Error("Method not found."); + } +}; +``` + + + + ```typescript title="index.ts" -import type { OnCronjobHandler } from "@metamask/snaps-sdk" +import type { OnCronjobHandler } from "@metamask/snaps-sdk"; +import { panel, heading, text } from "@metamask/snaps-sdk"; export const onCronjob: OnCronjobHandler = async ({ request }) => { switch (request.method) { @@ -64,6 +102,9 @@ export const onCronjob: OnCronjobHandler = async ({ request }) => { } ``` + + + :::tip Access data from cron jobs When accessing [encrypted data](data-storage.md#2-use-encrypted-storage) from cron jobs, MetaMask requires the user to enter their password if the wallet is locked. diff --git a/snaps/features/custom-ui/dialogs.md b/snaps/features/custom-ui/dialogs.md index c4aacb4f82d..80831ad3d30 100644 --- a/snaps/features/custom-ui/dialogs.md +++ b/snaps/features/custom-ui/dialogs.md @@ -3,6 +3,9 @@ description: Display custom alert, confirmation, or prompt screens in MetaMask. sidebar_position: 2 --- +import Tabs from "@theme/Tabs"; +import TabItem from "@theme/TabItem"; + # Dialogs You can display a dialog in the MetaMask UI using the @@ -35,6 +38,31 @@ To display an alert that can only be acknowledged, call [`snap_dialog`](../../reference/snaps-api.md#snap_dialog) with `type: "alert"`. The following example displays custom UI that alerts the user when something happens in the system: + + + +```tsx title="index.tsx" +import { Box, Text, Heading } from "@metamask/snaps-sdk/jsx"; + +await snap.request({ + method: "snap_dialog", + params: { + type: "alert", + content: ( + + Something happened in the system + The thing that happened is... + + ), + }, +}); + +// Code that should execute after the alert has been acknowledged. +``` + + + + ```javascript title="index.js" import { panel, text, heading } from "@metamask/snaps-sdk" @@ -52,6 +80,10 @@ await snap.request({ // Code that should execute after the alert has been acknowledged. ``` + + + +

Alert dialog example

@@ -63,6 +95,33 @@ To display a confirmation that can be accepted or rejected, call The following example displays custom UI that asks the user to confirm whether they would like to take an action: + + + +```tsx title="index.tsx" +import { Box, Text, Heading } from "@metamask/snaps-sdk/jsx"; + +const result = await snap.request({ + method: "snap_dialog", + params: { + type: "confirmation", + content: ( + + Would you like to take the action? + The action is... + + ), + }, +}); + +if (result === true) { + // Do the action. +} +``` + + + + ```javascript title="index.js" import { panel, text, heading } from "@metamask/snaps-sdk" @@ -82,6 +141,9 @@ if (result === true) { } ``` + + +

Confirmation dialog example

@@ -94,6 +156,32 @@ Prompt dialogs also accept a `placeholder` value that displays in the input fiel The following example displays custom UI that prompts the user to enter a wallet address: + + + +```tsx title="index.tsx" +import { Box, Text, Heading } from "@metamask/snaps-sdk/jsx"; + +const walletAddress = await snap.request({ + method: "snap_dialog", + params: { + type: "prompt", + content: ( + + What is the wallet address? + Please enter the wallet address to be monitored + + ), + placeholder: "0x123...", + }, +}); + +// walletAddress will be a string containing the address entered by the user. +``` + + + + ```javascript title="index.js" import { panel, text, heading } from "@metamask/snaps-sdk" @@ -112,6 +200,9 @@ const walletAddress = await snap.request({ // walletAddress will be a string containing the address entered by the user. ``` + + +

Prompt dialog example

diff --git a/snaps/features/custom-ui/home-pages.md b/snaps/features/custom-ui/home-pages.md index b7fcfc34e44..7fd7fe0285f 100644 --- a/snaps/features/custom-ui/home-pages.md +++ b/snaps/features/custom-ui/home-pages.md @@ -3,6 +3,9 @@ description: Display a dedicated UI page in MetaMask for your Snap. sidebar_position: 3 --- +import Tabs from "@theme/Tabs"; +import TabItem from "@theme/TabItem"; + # Home pages You can display a dedicated UI, or "home page," for your Snap within MetaMask. @@ -32,6 +35,28 @@ MetaMask calls this method when a user selects your Snap name in the Snaps menu. The following example displays custom UI that welcomes the user to the Snap's home page: + + + +```tsx title="index.tsx" +import type { OnHomePageHandler } from "@metamask/snaps-sdk"; +import { Box, Heading, Text } from "@metamask/snaps-sdk/jsx"; + +export const onHomePage: OnHomePageHandler = async () => { + return { + content: ( + + Hello world! + Welcome to my Snap home page! + + ), + }; +}; +``` + + + + ```typescript title="index.ts" import type { OnHomePageHandler } from "@metamask/snaps-sdk" import { panel, text, heading } from "@metamask/snaps-sdk" @@ -46,6 +71,9 @@ export const onHomePage: OnHomePageHandler = async () => { } ``` + + +

Home page example

diff --git a/snaps/features/custom-ui/index.md b/snaps/features/custom-ui/index.md index e886f0fe169..517e9c23f4f 100644 --- a/snaps/features/custom-ui/index.md +++ b/snaps/features/custom-ui/index.md @@ -5,13 +5,18 @@ sidebar_position: 4 # Custom UI +:::caution +This version of custom UI is deprecated. If you're building a new Snaps project, +use [custom UI with JSX](./with-jsx). JSX is supported in MetaMask Extension and Flask version 12+. +::: + You can display custom user interface (UI) components using the [`@metamask/snaps-sdk`](https://github.com/MetaMask/snaps/tree/main/packages/snaps-sdk) module when implementing the following features: - [Dialogs](dialogs.md) - [Home pages](home-pages.md) -- [Transaction insights](../../reference/entry-points.md#ontransaction) +- [Transaction insights](../transaction-insights.md) - [Signature insights](../signature-insights.md) To use custom UI, first install [`@metamask/snaps-sdk`](https://github.com/MetaMask/snaps/tree/main/packages/snaps-sdk) @@ -309,7 +314,7 @@ An object containing: #### Example ```js -import { input, form } from "@metamask/snaps-sdk" +import { button, input, form } from "@metamask/snaps-sdk"; const interfaceId = await snap.request({ method: "snap_createInterface", diff --git a/snaps/features/custom-ui/interactive-ui.md b/snaps/features/custom-ui/interactive-ui.md index d3ff0a7a81f..7eb54e057d3 100644 --- a/snaps/features/custom-ui/interactive-ui.md +++ b/snaps/features/custom-ui/interactive-ui.md @@ -16,6 +16,14 @@ The following interactive UI components are available: - [`form`](index.md#form) - [`input`](index.md#input) +The following interactive UI JSX components are available: + +- [`Button`](with-jsx.md#button) +- [`Dropdown`](with-jsx.md#dropdown) +- [`Field`](with-jsx.md#field) +- [`Form`](with-jsx.md#form) +- [`Input`](with-jsx.md#input) + ## Create an interactive interface Create an interactive interface using the diff --git a/snaps/features/custom-ui/with-jsx.md b/snaps/features/custom-ui/with-jsx.md new file mode 100644 index 00000000000..efc28a828e6 --- /dev/null +++ b/snaps/features/custom-ui/with-jsx.md @@ -0,0 +1,687 @@ +--- +description: Display custom user interface components using JSX. +sidebar_position: 4 +--- + +# Custom UI with JSX + +You can display custom user interface (UI) JSX components using the +[`@metamask/snaps-sdk`](https://github.com/MetaMask/snaps/tree/main/packages/snaps-sdk) module when +implementing the following features: + +- [Dialogs](dialogs.md) +- [Home pages](home-pages.md) +- [Transaction insights](../transaction-insights.md) +- [Signature insights](../signature-insights.md) + +:::note +JSX is supported in MetaMask Extension and Flask version 12+. New UI components will be added as JSX components. The previous function-based library is deprecated. +::: + +To use custom UI with JSX, first install [`@metamask/snaps-sdk`](https://github.com/MetaMask/snaps/tree/main/packages/snaps-sdk) +using the following command: + +```bash +yarn add @metamask/snaps-sdk +``` + +Then, whenever you're required to return a custom UI JSX component, import the components from the +SDK at `@metamask/snaps-sdk/jsx` and build your UI with them. +For example, to display a [`Box`](#box) (the [`panel`](./index.md#panel) function equivalent) using [`snap_dialog`](../../reference/snaps-api.md#snap_dialog): + +```javascript title="index.jsx" +import { Box, Heading, Text } from "@metamask/snaps-sdk/jsx"; + +await snap.request({ + method: "snap_dialog", + params: { + type: "alert", + content: ( + + Alert heading + Something happened in the system. + + ), + }, +}); +``` + +:::note +Note that JSX can only be used in `.jsx` or `.tsx` files. +::: + +## Components + +The following custom UI JSX components are available: + +### `Address` + +Outputs a formatted text field for an Ethereum address. +The address is automatically displayed with a jazzicon and truncated value. +Hovering the address shows the full value in a tooltip. + +#### Example + +```javascript title="index.jsx" +import { Box, Heading, Address } from "@metamask/snaps-sdk/jsx"; + +await snap.request({ + method: "snap_dialog", + params: { + type: "alert", + content: ( + + Are you sure you want to send tokens to this address? +
0x000000000000000000000000000000000000dEaD
+
+ ), + }, +}); +``` + +
+
+ Address UI example +
+
+ Address tooltip UI example +
+
+ +### `Bold` + +Outputs bold text. + +#### Example + +```javascript title="index.jsx" +import { Box, Heading, Text, Bold } from "@metamask/snaps-sdk/jsx"; + +await snap.request({ + method: "snap_dialog", + params: { + type: "alert", + content: ( + + Hello world! + + This is bold. + + + ), + }, +}); +``` + +### `Box` + +Outputs a box, which can be used as a container for other components. + +#### Props + +- `direction` - (Optional) The direction in which elements flow inside the box. + Possible values are `"horizontal"` or `"vertical"`. + The default is `"vertical"`. +- `alignment` - (Optional) The alignment of the elements inside the box. + Possible values are `"start"`, `"center"`, `"end"`, `"space-between"`, or `"space-around"`. + The default is `"start"`. + +#### Example + +```javascript title="index.jsx" +import { Box, Heading, Text } from "@metamask/snaps-sdk/jsx"; + +module.exports.onHomePage = async () => { + return { + content: ( + + Features + + Feature 1 + Feature 2 + Feature 3 + + + ), + }; +}; +``` + +

+Box UI example +

+ +### `Button` + +Outputs a button that the user can select. +For use in [interactive UI](interactive-ui.md). + +#### Props + +- `children`: `string` - The text of the button. +- `type` - (Optional) The type of button. + Possible values are `"button"` or `"submit"`. + The default is `"button"`. +- `name`: `string` - (Optional) The name that will be sent to [`onUserInput`](../../reference/entry-points.md#onuserinput) + when a user selects the button. +- `variant` - (Optional) Determines the appearance of the button. + Possible values are `"primary"` or `"secondary"`. + The default is `"primary"`. + +#### Example + +```javascript +import { Box, Heading, Button } from "@metamask/snaps-sdk/jsx"; + +const interfaceId = await snap.request({ + method: "snap_createInterface", + params: { + ui: ( + + Interactive interface + + + ), + }, +}); + +await snap.request({ + method: "snap_dialog", + params: { + type: "Alert", + id: interfaceId, + }, +}); + +``` + +

+Button UI example +

+ +### `Copyable` + +Outputs a read-only text field with a copy-to-clipboard shortcut. + +#### Example + +```javascript title="index.jsx" +import { Box, Text, Copyable } from "@metamask/snaps-sdk/jsx"; + +await snap.request({ + method: "snap_dialog", + params: { + type: "alert", + content: ( + + Your address: + 0x000000000000000000000000000000000000dEaD + + ), + }, +}); +``` + +

+Copyable UI example +

+ +### `Divider` + +Outputs a horizontal divider. + +#### Example + +```javascript title="index.jsx" +import { Box, Heading, Divider, Text } from "@metamask/snaps-sdk/jsx"; + +module.exports.onHomePage = async () => { + return { + content: ( + + Hello world! + + Welcome to my Snap home page! + + ), + }; +}; +``` + +

+Divider UI example +

+ +### `Dropdown` + +Outputs a dropdown for use in [interactive UI](interactive-ui.md). + +#### Props + +- `name`: `string` - The name sent to [`onUserInput`](../../reference/entry-points.md#onuserinput). +- `children`: `Option[]` - One or more `Option` components with the following props: + - `value`: `string` - The value sent to [`onUserInput`](../../reference/entry-points.md#onuserinput). + - `children`: `string` - The text displayed in the dropdown for that option. + +#### Example + +```js +import { Box, Text, Dropdown } from "@metamask/snaps-sdk/jsx"; + +const interfaceId = await snap.request({ + method: "snap_createInterface", + params: { + ui: ( + + Pick a currency + + + + + + ), + }, +}); + +await snap.request({ + method: "snap_dialog", + params: { + type: "Alert", + id: interfaceId, + }, +}); +``` + +
+
+ Dropdown UI example +
+
+ Active dropdown UI example +
+
+ +### `Field` + +Outputs a form field, wrapping a [`Dropdown`](#dropdown) or [`Input`](#input) to give it a label and optional error. + +#### Props + +- `label`: `string` - The label for the wrapped element. +- `error`: `string` - Any error for the wrapped element. Setting this changes the styling of the wrapped element to show that there is an error. +- `children` - The [`Dropdown`](#dropdown) or [`Input`](#input) element to be wrapped. + +#### Example + +```js +import { Field, Form, Input, Button } from "@metamask/snaps-sdk/jsx"; + +const interfaceId = await snap.request({ + method: "snap_createInterface", + params: { + ui: ( +
+ + + + +
+ ), + }, +}); + +await snap.request({ + method: "snap_dialog", + params: { + type: "Alert", + id: interfaceId, + }, +}); +``` + +

+Field example +

+ +### `Form` + +Outputs a form for use in [interactive UI](interactive-ui.md). + +#### Props + +- `name`: `string` - The name that will be sent to [`onUserInput`](../../reference/entry-points.md#onuserinput) + when a user interacts with the form. +- `children`: `array` - An array of [`Input`](#input) or [`Button`](#button) components. + +#### Example + +```js +import { Form, Input, Button } from "@metamask/snaps-sdk/jsx"; + +const interfaceId = await snap.request({ + method: "snap_createInterface", + params: { + ui: ( +
+ + +
+ ), + }, +}); + +await snap.request({ + method: "snap_dialog", + params: { + type: "Alert", + id: interfaceId, + }, +}); +``` + +

+Form UI example +

+ +### `Heading` + +Outputs a heading. +This is useful for [`Box`](#box) titles. + +#### Example + +```javascript title="index.jsx" +import { Box, Heading, Text } from "@metamask/snaps-sdk/jsx"; + +module.exports.onHomePage = async () => { + return { + content: ( + + Hello world! + Welcome to my Snap home page! + + ), + }; +}; +``` + +

+Divider UI example +

+ +### `Image` + +Outputs an image. +This component takes an inline SVG. +It does not support remote URLs. + +You can import SVG, PNG, and JPEG files using an import statement. +These files are automatically imported as SVG strings, so you can pass them directly to the `Image` component. + +The SVG is rendered within an `` tag, which prevents JavaScript or interaction events from +being supported. + +:::note +To disable image support, set the [`features.images`](../../reference/cli/options.md#featuresimages) +configuration option to `false`. +The default is `true`. +::: + +#### Props + +- `src`: `string` - An inline SVG. +- `alt`: `string` - An optional alternative text for the image. + +#### Example + +```javascript title="index.jsx" +import { Box, Heading, Text, Image } from "@metamask/snaps-sdk/jsx"; +import svgIcon from "./path/to/icon.svg"; + +module.exports.onHomePage = async () => { + return { + content: ( + + Hello world! + Welcome to my Snap home page! + + + ), + }; +}; +``` + +

+Divider UI example +

+ +:::note +See the [`@metamask/images-example-snap`](https://github.com/MetaMask/snaps/tree/main/packages/examples/packages/images) +package for a full example of implementing images. +::: + +### `Input` + +Outputs an input component for use in [interactive UI](interactive-ui.md). + +#### Props + +- `name`: `string` - The name that will be used as a key to the event sent to + [`onUserInput`](../../reference/entry-points.md#onuserinput) when the containing form is submitted. +- `type` - (Optional) The type of input. + Possible values are `"text"`, `"number"`, or `"password"`. + The default is `"text"`. +- `placeholder`: `string` - (Optional) The text displayed when the input is empty. +- `label`: `string` - (Optional) The text displayed alongside the input to label it. +- `value`: `string` - (Optional) The default value of the input. + +#### Example + +```js +import { Form, Input, Button } from "@metamask/snaps-sdk/jsx"; + +const interfaceId = await snap.request({ + method: "snap_createInterface", + params: { + ui: ( +
+ + +
+ ), + }, +}); + +await snap.request({ + method: "snap_dialog", + params: { + type: "Alert", + id: interfaceId, + }, +}); +``` + +

+Form UI example +

+ +### `Italic` + +Outputs italic text. + +#### Example + +```javascript title="index.jsx" +import { Box, Heading, Text, Italic } from "@metamask/snaps-sdk/jsx"; + +await snap.request({ + method: "snap_dialog", + params: { + type: "alert", + content: ( + + Hello world! + + This is italic. + + + ), + }, +}); +``` + +### `Link` + +Outputs a clickable link. + +#### Props + +- `href`: `string` - The URL to point to. +- `children`: `Array` - The link text. + +#### Example + +```javascript title="index.jsx" +import { Box, Heading, Link, Text } from "@metamask/snaps-sdk/jsx"; + +module.exports.onHomePage = async () => { + return { + content: ( + + Hello world! + + Download MetaMask. + + + Read the MetaMask docs at MetaMask docs. + + + ), + }; +}; +``` + +

+Links UI example +

+ +### `Row` + +Outputs a row with a label and value, which can be used for key-value data. + +#### Props + +- `label`: `string` - The label of the row. +- `variant` - (Optional) The variant of the label. + Possible values are `"default"`, `"error"`, or `"warning"`. +- `children` - The value of the row, which can be a [`Text`](#text), [`Image`](#image), or + [`Address`](#address) component. + +#### Example + +```javascript title="index.jsx" +import { Box, Row, Text, Address } from "@metamask/snaps-sdk/jsx"; + +await snap.request({ + method: "snap_dialog", + params: { + type: "alert", + content: ( + + +
0x000000000000000000000000000000000000dEaD
+
+ + 1.78 ETH + +
+ ), + }, +}); +``` + +

+Row UI example +

+ +### `Spinner` + +Outputs a loading indicator. + +#### Example + +```javascript title="index.jsx" +import { Box, Heading, Spinner } from "@metamask/snaps-sdk/jsx"; + +await snap.request({ + method: "snap_dialog", + params: { + type: "alert", + content: ( + + Please wait... + + + ), + }, +}); +``` + +

+Spinner UI example +

+ +### `Text` + +Outputs text. + +#### Example + +```javascript title="index.jsx" +import { Box, Heading, Text } from "@metamask/snaps-sdk/jsx"; + +module.exports.onHomePage = async () => { + return { + content: ( + + Hello world! + Welcome to my Snap home page! + + ), + }; +}; +``` + +

+Text UI example +

+ +## Emojis + +Text-based components (such as [`Heading`](#heading) and [`Text`](#text)) accept emojis. + +#### Example + +```javascript title="index.jsx" +import { Box, Heading, Text } from "@metamask/snaps-sdk/jsx"; + +await snap.request({ + method: "snap_dialog", + params: { + type: "alert", + content: ( + + Hello world! + This is an apple 🍎 and this is an orange 🍊. + + ), + }, +}); +``` + +

+Emojis UI example +

\ No newline at end of file diff --git a/snaps/features/lifecycle-hooks.md b/snaps/features/lifecycle-hooks.md index ce7db582ddd..f748b857f87 100644 --- a/snaps/features/lifecycle-hooks.md +++ b/snaps/features/lifecycle-hooks.md @@ -3,6 +3,9 @@ sidebar_position: 6 description: Call an action when your Snap is installed or updated. --- +import Tabs from "@theme/Tabs"; +import TabItem from "@theme/TabItem"; + # Lifecycle hooks You can implement lifecycle hooks to automatically run an action, such as displaying a dialog or @@ -30,6 +33,35 @@ For example, you can use `onInstall` to perform any initialization that is requi The following example displays an [alert dialog](custom-ui/dialogs.md#display-an-alert-dialog) upon installation: + + + + +```tsx title="index.tsx" +import type { OnInstallHandler } from "@metamask/snaps-sdk"; +import { Box, Heading, Text } from "@metamask/snaps-sdk/jsx"; + +export const onInstall: OnInstallHandler = async () => { + await snap.request({ + method: "snap_dialog", + params: { + type: "alert", + content: ( + + Installation successful + + To use this Snap, visit the companion dapp at
metamask.io. + + + ), + }, + }); +}; +``` + + + + ```typescript title="index.ts" import type { OnInstallHandler } from "@metamask/snaps-sdk" import { heading, panel, text } from "@metamask/snaps-sdk" @@ -50,6 +82,9 @@ export const onInstall: OnInstallHandler = async () => { } ``` + + + ### 3. Run an action on update To run an action when a user updates your Snap, expose the @@ -58,6 +93,34 @@ For example, you can use `onUpdate` to perform any migrations that are required The following example displays an [alert dialog](custom-ui/dialogs.md#display-an-alert-dialog) upon update: + + + + +```tsx title="index.tsx" +import type { OnUpdateHandler } from "@metamask/snaps-sdk"; +import { Box, Heading, Text } from "@metamask/snaps-sdk/jsx"; + +export const onUpdate: OnUpdateHandler = async () => { + await snap.request({ + method: "snap_dialog", + params: { + type: "alert", + content: ( + + Update successful + New features added in this version: + Added a dialog that appears when updating. + + ), + }, + }); +}; +``` + + + + ```typescript title="index.ts" import type { OnUpdateHandler } from "@metamask/snaps-sdk" import { heading, panel, text } from "@metamask/snaps-sdk" @@ -77,6 +140,9 @@ export const onUpdate: OnUpdateHandler = async () => { } ``` + + + ## Example See the [`@metamask/lifecycle-hooks-example-snap`](https://github.com/MetaMask/snaps/tree/main/packages/examples/packages/lifecycle-hooks) diff --git a/snaps/features/signature-insights.md b/snaps/features/signature-insights.md index dc06781a54b..4c70c39d575 100644 --- a/snaps/features/signature-insights.md +++ b/snaps/features/signature-insights.md @@ -124,6 +124,36 @@ level of `SeverityLevel.Critical`. The following is an example implementation of `onSignature`: + + + +```tsx title="index.tsx" +import type { OnSignatureHandler, SeverityLevel } from "@metamask/snaps-sdk"; +import { Box, Heading, Text } from "@metamask/snaps-sdk/jsx"; + +export const onSignature: OnSignatureHandler = async ({ + signature, + signatureOrigin, +}) => { + const insights = /* Get insights based on custom logic */; + return { + content: ( + + My Signature Insights + Here are the insights: + {insights.map((insight) => ( + {insight.value} + ))} + + ), + severity: SeverityLevel.Critical, + }; +}; +``` + + + + ```typescript title="index.ts" import type { OnSignatureHandler, SeverityLevel } from "@metamask/snaps-sdk"; import { panel, heading, text } from "@metamask/snaps-sdk"; @@ -144,6 +174,9 @@ export const onSignature: OnSignatureHandler = async ({ }; ``` + + + When your Snap returns a signature insight with a `severity` of `SeverityLevel.Critical`, the custom UI displays in a modal after the user selects the **Sign** button. For example: diff --git a/snaps/features/transaction-insights.md b/snaps/features/transaction-insights.md index 716ea9df48c..99f8ffd28bb 100644 --- a/snaps/features/transaction-insights.md +++ b/snaps/features/transaction-insights.md @@ -4,6 +4,9 @@ toc_max_heading_level: 4 sidebar_position: 13 --- +import Tabs from "@theme/Tabs"; +import TabItem from "@theme/TabItem"; + # Transaction insights You can provide transaction insights in MetaMask's transaction confirmation window before a user @@ -43,6 +46,36 @@ handler method. The following is an example implementation of `onTransaction`: + + + +```tsx title="index.tsx" +import type { OnTransactionHandler } from "@metamask/snaps-sdk"; +import { Box, Heading, Text } from "@metamask/snaps-sdk/jsx"; + +export const onTransaction: OnTransactionHandler = async ({ + transaction, + chainId, + transactionOrigin, +}) => { + const insights = /* Get insights */; + return { + content: ( + + My Transaction Insights + Here are the insights: + {insights.map((insight) => ( + {insight.value} + ))} + + ), + }; +}; +``` + + + + ```typescript title="index.ts" import type { OnTransactionHandler } from "@metamask/snaps-sdk"; import { panel, heading, text } from "@metamask/snaps-sdk"; @@ -63,6 +96,10 @@ export const onTransaction: OnTransactionHandler = async ({ }; ``` + + + + The Snap tab in the transaction confirmation window displays the transaction insights:

@@ -77,6 +114,38 @@ The Snap tab in the transaction confirmation window displays the transaction ins A Snap providing transaction insights can return an optional severity level of `"critical"`. MetaMask shows a modal with the warning before the user can confirm the transaction. + + + +```tsx title="index.tsx" +import type { OnTransactionHandler } from "@metamask/snaps-sdk"; +import { Box, Heading, Text } from "@metamask/snaps-sdk/jsx"; + +export const onTransaction: OnTransactionHandler = async ({ + transaction, + chainId, + transactionOrigin, +}) => { + const insights = /* Get insights */; + return { + content: ( + + My Transaction Insights + Here are the insights: + {insights.map((insight) => ( + {insight.value} + ))} + + ), + // highlight-next-line + severity: "critical", + }; +}; +``` + + + + ```typescript title="index.ts" import type { OnTransactionHandler } from "@metamask/snaps-sdk"; import { panel, heading, text } from "@metamask/snaps-sdk"; @@ -99,6 +168,9 @@ export const onTransaction: OnTransactionHandler = async ({ }; ``` + + +

Transaction insights warning

diff --git a/snaps/get-started/quickstart.md b/snaps/get-started/quickstart.md index b58e51c8250..10fefbbec4d 100644 --- a/snaps/get-started/quickstart.md +++ b/snaps/get-started/quickstart.md @@ -3,7 +3,9 @@ description: Get started quickly using the create-snap starter kit. sidebar_position: 2 --- -import YoutubeEmbed from '@site/src/components/YoutubeEmbed'; +import Tabs from "@theme/Tabs"; +import TabItem from "@theme/TabItem"; +import YoutubeEmbed from "@site/src/components/YoutubeEmbed"; # Snaps quickstart @@ -89,6 +91,50 @@ You can customize your Snap by editing `index.ts` in the `packages/snap/src` fol `index.ts` contains an example request that uses the [`snap_dialog`](../reference/snaps-api.md#snapdialog) method to display a custom confirmation screen: + + + +```tsx title="index.tsx" +import type { OnRpcRequestHandler } from "@metamask/snaps-sdk"; +import { Box, Text, Bold } from "@metamask/snaps-sdk/jsx"; + +/** + * Handle incoming JSON-RPC requests, sent through wallet_invokeSnap. + * + * @param args - The request handler arguments as an object. + * @param args.origin - The origin of the request, e.g., the website that invoked the Snap. + * @param args.request - A validated JSON-RPC request object. + * @returns The result of snap_dialog. + * @throws If the request method is not valid for this Snap. + */ +export const onRpcRequest: OnRpcRequestHandler = async ({ + origin, + request, +}) => { + switch (request.method) { + case "hello": + return snap.request({ + method: "snap_dialog", + params: { + type: "confirmation", + content: ( + + Hello, {origin}! + This custom confirmation is just for display purposes. + But you can edit the Snap source code to make it do something, if you want to! + + ), + }, + }); + default: + throw new Error("Method not found."); + } +}; +``` + + + + ```ts title="index.ts" import type { OnRpcRequestHandler } from "@metamask/snaps-sdk" import { panel, text } from "@metamask/snaps-sdk" @@ -127,6 +173,9 @@ export const onRpcRequest: OnRpcRequestHandler = async ({ } ``` + + + Edit the text in any `text()` component and select the **Reconnect** button on the front-end to re-install the Snap. diff --git a/snaps/how-to/use-environment-variables.md b/snaps/how-to/use-environment-variables.md index 67ac057db4f..16ba0abec71 100644 --- a/snaps/how-to/use-environment-variables.md +++ b/snaps/how-to/use-environment-variables.md @@ -91,19 +91,47 @@ Snaps CLI: 3. You can also use environment variables directly in your Snap. For example: - ```typescript title="index.ts" - import { panel, text, heading } from "@metamask/snaps-sdk" - - await snap.request({ - method: "snap_dialog", - params: { - type: "alert", - content: panel([ - heading("This custom alert is just for display purposes."), - text( - `SNAP_ENV is ${process.env.SNAP_ENV}, PUBLIC_KEY is ${process.env.PUBLIC_KEY}` - ), - ]), - }, - }) - ``` + + + + ```tsx title="index.tsx" + import { Box, Text, Heading } from "@metamask/snaps-sdk/jsx"; + + await snap.request({ + method: "snap_dialog", + params: { + type: "alert", + content: ( + + This custom alert is just for display purposes. + + SNAP_ENV is {process.env.SNAP_ENV}, PUBLIC_KEY is {process.env.PUBLIC_KEY} + + + ), + }, + }); + ``` + + + + + ```typescript title="index.ts" + import { panel, text, heading } from "@metamask/snaps-sdk" + + await snap.request({ + method: "snap_dialog", + params: { + type: "alert", + content: panel([ + heading("This custom alert is just for display purposes."), + text( + `SNAP_ENV is ${process.env.SNAP_ENV}, PUBLIC_KEY is ${process.env.PUBLIC_KEY}` + ), + ]), + }, + }) + ``` + + + diff --git a/snaps/learn/tutorials/gas-estimation.md b/snaps/learn/tutorials/gas-estimation.md index 5ac32b8bf92..da8a3ba1f6e 100644 --- a/snaps/learn/tutorials/gas-estimation.md +++ b/snaps/learn/tutorials/gas-estimation.md @@ -3,6 +3,9 @@ description: Create a Snap that estimates gas fees. sidebar_position: 1 --- +import Tabs from "@theme/Tabs"; +import TabItem from "@theme/TabItem"; + # Create a Snap to estimate gas fees This tutorial walks you through creating a Snap that estimates gas fees. @@ -175,26 +178,51 @@ only one method, `hello`. For the `hello` method, the handler returns a call to MetaMask with the parameters to display a dialog, and passes some static strings. -Since `getFees()` returns a promise, you must use `then()` to resolve it in your `hello` method. Update the `hello` method with the following code: + + + +```tsx title="index.tsx" +case "hello": + const fees = await getFees(); + return snap.request({ + method: 'snap_dialog', + params: { + type: "alert", + content: ( + + Hello, {origin}! + Current gas fee estimates: + {fees} + + ), + } + }); +``` + + + + ```typescript title="index.ts" case "hello": - return getFees().then(fees => { - return snap.request({ - method: 'snap_dialog', - params: { - type: "alert", - content: panel([ - text(`Hello, **${origin}**!`), - text("Current gas fee estimates:"), - copyable(fees), - ]), - } - }); + const fees = await getFees(); + return snap.request({ + method: 'snap_dialog', + params: { + type: "alert", + content: panel([ + text(`Hello, **${origin}**!`), + text("Current gas fee estimates:"), + copyable(fees), + ]), + } }); ``` + + + ### 5. Build and test the Snap To build and test your Snap: diff --git a/snaps/learn/tutorials/transaction-insights.md b/snaps/learn/tutorials/transaction-insights.md index d5452462667..f39241876f6 100644 --- a/snaps/learn/tutorials/transaction-insights.md +++ b/snaps/learn/tutorials/transaction-insights.md @@ -3,6 +3,9 @@ description: Create a Snap that provides transaction insights. sidebar_position: 2 --- +import Tabs from "@theme/Tabs"; +import TabItem from "@theme/TabItem"; + # Create a Snap to calculate gas fee percentages This tutorial walks you through creating a Snap that calculates the percentage of gas fees that @@ -100,6 +103,58 @@ You do not need any permissions other than `endowment:transaction-insight` and ` To calculate and display the gas fees a user would pay as a percentage of their outgoing transaction, replace the code in `packages/snap/src/index.ts` with the following: + + + +```tsx title="index.tsx" +import type { OnTransactionHandler } from "@metamask/snaps-sdk"; +import { Box, Heading, Text, Bold } from "@metamask/snaps-sdk/jsx"; + +// Handle outgoing transactions. +export const onTransaction: OnTransactionHandler = async ({ transaction }) => { + + // Use the Ethereum provider to fetch the gas price. + const currentGasPrice = await ethereum.request({ + method: "eth_gasPrice", + }) as string; + + // Get fields from the transaction object. + const transactionGas = parseInt(transaction.gas as string, 16); + const currentGasPriceInWei = parseInt(currentGasPrice ?? "", 16); + const maxFeePerGasInWei = parseInt(transaction.maxFeePerGas as string, 16); + const maxPriorityFeePerGasInWei = parseInt( + transaction.maxPriorityFeePerGas as string, + 16, + ); + + // Calculate gas fees the user would pay. + const gasFees = Math.min( + maxFeePerGasInWei * transactionGas, + (currentGasPriceInWei + maxPriorityFeePerGasInWei) * transactionGas, + ); + + // Calculate gas fees as percentage of transaction. + const transactionValueInWei = parseInt(transaction.value as string, 16); + const gasFeesPercentage = (gasFees / (gasFees + transactionValueInWei)) * 100; + + // Display percentage of gas fees in the transaction insights UI. + return { + content: ( + + Transaction insights Snap + + As set up, you are paying {gasFeesPercentage.toFixed(2)}% + in gas fees for this transaction. + + + ), + }; +}; +``` + + + + ```typescript title="index.ts" import type { OnTransactionHandler } from "@metamask/snaps-sdk" import { heading, panel, text } from "@metamask/snaps-sdk" @@ -143,6 +198,9 @@ export const onTransaction: OnTransactionHandler = async ({ transaction }) => { } ``` + + + :::tip If you have previously developed a dapp, you're likely familiar with accessing the Ethereum provider using `window.ethereum`. In a Snap, the `window` object is not available. @@ -189,6 +247,27 @@ To build and test your Snap: The Snap should display a gas fee percentage for ETH transfers initiated by the user. For contract interactions, add the following code to the beginning of the `onTransaction` entry point: + + + +```tsx title="index.tsx" +if (typeof transaction.data === "string" && transaction.data !== "0x") { + return { + content: ( + + Percent Snap + + This Snap only provides transaction insights for simple ETH transfers. + + + ), + }; +} +``` + + + + ```typescript title="index.ts" if (typeof transaction.data === "string" && transaction.data !== "0x") { return { @@ -202,6 +281,9 @@ if (typeof transaction.data === "string" && transaction.data !== "0x") { } ``` + + + ### 6. Next steps The initial project has generic names in multiple places. diff --git a/snaps/reference/entry-points.md b/snaps/reference/entry-points.md index cd25bf0edb8..2b6765a7bd2 100644 --- a/snaps/reference/entry-points.md +++ b/snaps/reference/entry-points.md @@ -100,24 +100,26 @@ One of the following: #### Example - + -```typescript title="index.ts" -import type { OnHomePageHandler } from "@metamask/snaps-sdk" -import { panel, text, heading } from "@metamask/snaps-sdk" +```tsx title="index.tsx" +import type { OnHomePageHandler } from "@metamask/snaps-sdk"; +import { Box, Heading, Text } from "@metamask/snaps-sdk/jsx"; export const onHomePage: OnHomePageHandler = async () => { return { - content: panel([ - heading("Hello world!"), - text("Welcome to my Snap home page!"), - ]), - } -} + content: ( + + Hello world! + Welcome to my Snap home page! + + ), + }; +}; ``` - + ```js title="index.js" import { panel, text, heading } from "@metamask/snaps-sdk" @@ -153,30 +155,32 @@ None. #### Example - + -```typescript title="index.ts" -import type { OnInstallHandler } from "@metamask/snaps-sdk" -import { heading, panel, text } from "@metamask/snaps-sdk" +```tsx title="index.tsx" +import type { OnInstallHandler } from "@metamask/snaps-sdk"; +import { Box, Heading, Text } from "@metamask/snaps-sdk/jsx"; export const onInstall: OnInstallHandler = async () => { await snap.request({ method: "snap_dialog", params: { type: "alert", - content: panel([ - heading("Thank you for installing my Snap"), - text( - "To use this Snap, visit the companion dapp at [metamask.io](https://metamask.io)." - ), - ]), + content: ( + + Thank you for installing my Snap + + To use this Snap, visit the companion dapp at metamask.io. + + + ), }, - }) -} + }); +}; ``` - + ```js title="index.js" import { heading, panel, text } from "@metamask/snaps-sdk" @@ -200,6 +204,7 @@ module.exports.onInstall = async () => { + ## `onKeyringRequest` To implement the [Account Management API](keyring-api/account-management/index.md) to integrate @@ -428,11 +433,11 @@ An object containing: #### Example - + -```typescript title="index.ts" +```tsx title="index.tsx" import type { OnSignatureHandler, SeverityLevel } from "@metamask/snaps-sdk"; -import { panel, heading, text } from "@metamask/snaps-sdk"; +import { Box, Heading, Text } from "@metamask/snaps-sdk/jsx"; export const onSignature: OnSignatureHandler = async ({ signature, @@ -440,24 +445,28 @@ export const onSignature: OnSignatureHandler = async ({ }) => { const insights = /* Get insights */; return { - content: panel([ - heading("My Signature Insights"), - text("Here are the insights:"), - ...(insights.map((insight) => text(insight.value))), - ]), + content: ( + + My Signature Insights + Here are the insights: + {insights.map((insight) => ( + {insight.value} + ))} + + ), severity: SeverityLevel.Critical, }; }; ``` - + -```js title="index.js" -import { SeverityLevel } from "@metamask/snaps-sdk"; +```typescript title="index.ts" +import type { OnSignatureHandler, SeverityLevel } from "@metamask/snaps-sdk"; import { panel, heading, text } from "@metamask/snaps-sdk"; -module.exports.onSignature = async ({ +export const onSignature: OnSignatureHandler = async ({ signature, signatureOrigin, }) => { @@ -476,6 +485,7 @@ module.exports.onSignature = async ({ + ## `onTransaction` To provide [transaction insights](../features/transaction-insights.md) before a user signs a @@ -512,11 +522,11 @@ An object containing: #### Example - + -```typescript title="index.ts" +```tsx title="index.tsx" import type { OnTransactionHandler } from "@metamask/snaps-sdk"; -import { panel, heading, text } from "@metamask/snaps-sdk"; +import { Box, Heading, Text } from "@metamask/snaps-sdk/jsx"; export const onTransaction: OnTransactionHandler = async ({ transaction, @@ -525,22 +535,27 @@ export const onTransaction: OnTransactionHandler = async ({ }) => { const insights = /* Get insights */; return { - content: panel([ - heading("My Transaction Insights"), - text("Here are the insights:"), - ...(insights.map((insight) => text(insight.value))), - ]), + content: ( + + My Transaction Insights + Here are the insights: + {insights.map((insight) => ( + {insight.value} + ))} + + ), }; }; ``` - + -```js title="index.js" +```typescript title="index.ts" +import type { OnTransactionHandler } from "@metamask/snaps-sdk"; import { panel, heading, text } from "@metamask/snaps-sdk"; -module.exports.onTransaction = async ({ +export const onTransaction: OnTransactionHandler = async ({ transaction, chainId, transactionOrigin, @@ -577,34 +592,37 @@ None. #### Example - + -```typescript title="index.ts" -import type { OnUpdateHandler } from "@metamask/snaps-sdk" -import { heading, panel, text } from "@metamask/snaps-sdk" +```tsx title="index.tsx" +import type { OnUpdateHandler } from "@metamask/snaps-sdk"; +import { Box, Heading, Text } from "@metamask/snaps-sdk/jsx"; export const onUpdate: OnUpdateHandler = async () => { await snap.request({ method: "snap_dialog", params: { type: "alert", - content: panel([ - heading("Thank you for updating my Snap"), - text("New features added in this version:"), - text("Added a dialog that appears when updating."), - ]), + content: ( + + Thank you for updating my Snap + New features added in this version: + Added a dialog that appears when updating. + + ), }, }) } ``` - + -```js title="index.js" -import { heading, panel, text } from "@metamask/snaps-sdk" +```typescript title="index.ts" +import type { OnUpdateHandler } from "@metamask/snaps-sdk"; +import { heading, panel, text } from "@metamask/snaps-sdk"; -module.exports.onUpdate = async () => { +export const onUpdate: OnUpdateHandler = async () => { await snap.request({ method: "snap_dialog", params: { diff --git a/snaps/reference/snaps-api.md b/snaps/reference/snaps-api.md index e6cfa2f55ea..d85837deee4 100644 --- a/snaps/reference/snaps-api.md +++ b/snaps/reference/snaps-api.md @@ -48,8 +48,34 @@ Return value depends on the dialog `type`: #### Example -```javascript title="index.js" -import { panel, text, heading } from "@metamask/snaps-sdk" + + + +```tsx title="index.tsx" +import { Box, Heading, Text } from "@metamask/snaps-sdk/jsx"; + +const walletAddress = await snap.request({ + method: "snap_dialog", + params: { + type: "prompt", + content: ( + + What is the wallet address? + Please enter the wallet address to be monitored + + ), + placeholder: "0x123...", + }, +}); + +// walletAddress will be a string containing the address entered by the user. +``` + + + + +```typescript title="index.ts" +import { panel, text, heading } from "@metamask/snaps-sdk"; const walletAddress = await snap.request({ method: "snap_dialog", @@ -66,6 +92,9 @@ const walletAddress = await snap.request({ // walletAddress will be a string containing the address entered by the user. ``` + + + ## `snap_getBip32Entropy` :::danger important @@ -465,8 +494,37 @@ The user's locale setting as a [language code](https://github.com/MetaMask/metam #### Example -```javascript title="index.js" -import { panel, text } from "@metamask/snaps-sdk" + + + +```tsx title="index.tsx" +import { Box, Text } from "@metamask/snaps-sdk/jsx"; + +const locale = await snap.request({ method: "snap_getLocale" }); + +let greeting = "Hello"; +if(locale === "es") { + greeting = "Hola"; +} + +await snap.request({ + method: "snap_dialog", + params: { + type: "alert", + content: ( + + {greeting} + + ), + }, +}); +``` + + + + +```typescript title="index.ts" +import { panel, text } from "@metamask/snaps-sdk"; const locale = await snap.request({ method: "snap_getLocale" }) @@ -484,6 +542,9 @@ await snap.request({ }) ``` + + + ## `snap_manageAccounts` Manages [account management Snap](../features/custom-evm-accounts/index.md) accounts. diff --git a/src/theme/Tabs/index.tsx b/src/theme/Tabs/index.tsx new file mode 100644 index 00000000000..d519f2d320c --- /dev/null +++ b/src/theme/Tabs/index.tsx @@ -0,0 +1,177 @@ +import React, {cloneElement, type ReactElement} from 'react'; +import clsx from 'clsx'; +import { + useScrollPositionBlocker, + useTabs, + sanitizeTabsChildren, + type TabItemProps, +} from '@docusaurus/theme-common/internal'; +import useIsBrowser from '@docusaurus/useIsBrowser'; +import type {Props} from '@theme/Tabs'; +import styles from './styles.module.css'; + +function TabList({ + className, + block, + selectedValue, + selectValue, + tabValues, +}: Props & ReturnType) { + console.log(tabValues); + const tabRefs: (HTMLLIElement | null)[] = []; + const {blockElementScrollPositionUntilNextRender} = + useScrollPositionBlocker(); + + const handleTabChange = ( + event: + | React.FocusEvent + | React.MouseEvent + | React.KeyboardEvent, + ) => { + const newTab = event.currentTarget; + const newTabIndex = tabRefs.indexOf(newTab); + const newTabValue = tabValues[newTabIndex]!.value; + + if (newTabValue !== selectedValue) { + blockElementScrollPositionUntilNextRender(newTab); + selectValue(newTabValue); + } + }; + + const handleKeydown = (event: React.KeyboardEvent) => { + let focusElement: HTMLLIElement | null = null; + + switch (event.key) { + case 'Enter': { + handleTabChange(event); + break; + } + case 'ArrowRight': { + const nextTab = tabRefs.indexOf(event.currentTarget) + 1; + focusElement = tabRefs[nextTab] ?? tabRefs[0]!; + break; + } + case 'ArrowLeft': { + const prevTab = tabRefs.indexOf(event.currentTarget) - 1; + focusElement = tabRefs[prevTab] ?? tabRefs[tabRefs.length - 1]!; + break; + } + default: + break; + } + + focusElement?.focus(); + }; + + return ( +
    + {tabValues.map(({value, label, attributes}) => ( +
  • tabRefs.push(tabControl)} + onKeyDown={handleKeydown} + onClick={handleTabChange} + {...attributes} + className={clsx( + 'tabs__item', + styles.tabItem, + attributes?.className as string, + { + 'tabs__item--active': selectedValue === value, + }, + )}> + {label ?? value} +
  • + ))} +
+ ); +} + +function TabContent({ + lazy, + children, + selectedValue, +}: Props & ReturnType) { + const childTabs = (Array.isArray(children) ? children : [children]).filter( + Boolean, + ) as ReactElement[]; + if (lazy) { + const selectedTabItem = childTabs.find( + (tabItem) => tabItem.props.value === selectedValue, + ); + if (!selectedTabItem) { + // fail-safe or fail-fast? not sure what's best here + return null; + } + return cloneElement(selectedTabItem, {className: 'margin-top--md'}); + } + return ( +
+ {childTabs.map((tabItem, i) => + cloneElement(tabItem, { + key: i, + hidden: tabItem.props.value !== selectedValue, + }), + )} +
+ ); +} + +function TabsComponent(props: Props): JSX.Element { + const tabs = useTabs(props); + /** + * Tabs and TabItems aren't rendered in a straightforward manner. + * Swizzling the TabItem component has no effect: the TabItem is used only for its data. + * The actual tab items are rendered by the TabList component above. + * Here we are adding custom styling to a tab by combining the tab values from the hook + * with the props of the TabItem. + */ + const finalTabs = { + ...tabs, + tabValues: tabs.tabValues.map((tabValue, idx) => ({ + ...tabValue, + attributes: { + ...tabValue.attributes, + className: clsx( + tabValue.attributes?.className, + { + [styles.flaskOnly]: props.children[idx]?.props.flaskOnly, + [styles.deprecated]: props.children[idx]?.props.deprecated + } + ) + } + })) + } + return ( +
+ + +
+ ); +} + +export default function Tabs(props: Props): JSX.Element { + const isBrowser = useIsBrowser(); + return ( + + {sanitizeTabsChildren(props.children)} + + ); +} diff --git a/src/theme/Tabs/styles.module.css b/src/theme/Tabs/styles.module.css new file mode 100644 index 00000000000..0638d111d6b --- /dev/null +++ b/src/theme/Tabs/styles.module.css @@ -0,0 +1,27 @@ +.tabList { + margin-bottom: var(--ifm-leading); +} + +.tabItem { + margin-top: 0 !important; +} + +.flaskOnly::after { + content: "Flask"; + margin-left: 0.5em; + background-color: var(--mm-flask-background-color); + color: var(--mm-flask-color); + border-radius: 4px; + padding: 2px 4px; + font-size: 0.8em; +} + +.deprecated::after { + content: "deprecated"; + margin-left: 0.5em; + background-color: var(--ifm-color-warning-contrast-background); + color: var(--ifm-color-warning-contrast-foreground); + border-radius: 4px; + padding: 2px 4px; + font-size: 0.8em; +} \ No newline at end of file diff --git a/wallet/how-to/use-sdk/gaming/unity/index.md b/wallet/how-to/use-sdk/gaming/unity/index.md index 105ab1b2774..687a83fbdd0 100644 --- a/wallet/how-to/use-sdk/gaming/unity/index.md +++ b/wallet/how-to/use-sdk/gaming/unity/index.md @@ -6,7 +6,7 @@ tags: - Unity SDK --- -import YoutubeEmbed from '@site/src/components/YoutubeEmbed'; +import YoutubeEmbed from "@site/src/components/YoutubeEmbed"; # Use MetaMask SDK with Unity