From 462174c03c5f3f4d032aefa3f9e99aded5a1fd4d Mon Sep 17 00:00:00 2001 From: Jay Date: Tue, 2 Apr 2024 17:54:51 +0800 Subject: [PATCH] Support ahUSDT on mainnet and PINK (#18) * Support ahUSDT on mainnet and PINK * Add dev deploy * Update website metadata * Improve no-data style * Add gap between chain options * Fix fee asset id --- .github/workflows/deploy-dev.yml | 31 ++++++++ public/images/asset/pink.jpg | Bin 0 -> 23607 bytes public/images/network/darwinia.png | Bin 0 -> 1099 bytes public/images/warning.svg | 7 ++ src/app/globals.css | 2 +- src/app/layout.tsx | 4 +- src/components/address-input.tsx | 6 +- src/components/asset-select.tsx | 17 +++-- src/components/balance-input.tsx | 17 +++-- src/components/chain-select.tsx | 13 ++-- src/components/transfer.tsx | 35 ++++++++- src/config/chains/assethub-polkadot-chain.ts | 75 +++++++++++++++++++ src/config/chains/assethub-rococo-chain.ts | 13 +++- src/config/chains/darwinia-chain.ts | 75 +++++++++++++++++++ src/config/chains/index.ts | 2 + src/config/chains/pangolin-chain.ts | 8 +- src/hooks/use-balance.ts | 10 ++- src/libs/bridge/base.ts | 8 ++ src/libs/bridge/evm.ts | 4 +- src/libs/bridge/substrate.ts | 75 ++++++++++++------- src/providers/rainbow-provider.tsx | 4 +- src/providers/transfer-provider.tsx | 10 ++- src/types/asset.ts | 2 +- src/types/chain.ts | 14 +++- src/types/cross.ts | 2 + src/utils/chain.ts | 9 ++- src/utils/cross.ts | 6 +- tailwind.config.ts | 2 +- 28 files changed, 366 insertions(+), 85 deletions(-) create mode 100644 .github/workflows/deploy-dev.yml create mode 100644 public/images/asset/pink.jpg create mode 100644 public/images/network/darwinia.png create mode 100644 public/images/warning.svg create mode 100644 src/config/chains/assethub-polkadot-chain.ts create mode 100644 src/config/chains/darwinia-chain.ts diff --git a/.github/workflows/deploy-dev.yml b/.github/workflows/deploy-dev.yml new file mode 100644 index 0000000..e073dab --- /dev/null +++ b/.github/workflows/deploy-dev.yml @@ -0,0 +1,31 @@ +name: Deploy development + +on: + pull_request: + workflow_dispatch: + +jobs: + deploy-package: + name: Deploy package + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - uses: actions/checkout@v2 + with: + repository: darwinia-network/devops + path: .github + + - uses: ./.github/actions/smart-vercel + name: Deploy app + with: + vercel_token: ${{ secrets.VERCEL_TOKEN }} + vercel_group: itering + preview_output: true + alias_domain: "crosschain-dev" + project_name: "crosschain-ui" + script_run: false + dist_path: . + enable_notify_slack: true + slack_channel: darwinia-apps + slack_webhook: ${{ secrets.SLACK_INCOMING_WEBHOOK_URL }} diff --git a/public/images/asset/pink.jpg b/public/images/asset/pink.jpg new file mode 100644 index 0000000000000000000000000000000000000000..14000f7dbdafa3e908bf881b2c9187ffba46a358 GIT binary patch literal 23607 zcmbrl1ymeO&?vfCAUG@*+}+&??(PH$?(XjH8YH;81$TFMcXtgC7c z?d(iVcUMh!ZFfy=RrSa6$2I_2N=#A=00ssCfPp@Mk6rK_Nnv3<1tobgNg2_9D!}8c z46Pj@836!m8z%=PaUnttO)Wyee*=9(M>|0U1)2X=^uM8xi+{NT0CRMIdHrvd|4+AY zM#heYpbo--8gd%iIXHpvuOM8`)yeKJ9tXnF49)b7KzIQNr*!~z5QIco0r#`Y%rV7dQA9|2q~!Lo)|!P#Y@{PHJuC4C=!_@OLEe#x|&^CZKX-(8mhY0tEjh`~Q-uqY2AjexM=4O922-dmkTn)Bpf<1_1CD z`tk86@8jbw9{_+@1^~K~{)^r=2_()-P1G z1q=cO?4$qhgaCsA`@5k26TrYBAVIx^0o7uI0l*>tM z{_lLP-0SKlB)*xfq~<50C{E(1NTp1tn*0PO33X9nAsUgfoDo)#lcZNE~^N5y8^B9UxX&bAgxWs*oUOu(IJ!i-t(NIKp!L@!{7<%&T=XLJUBxW9j>!*& z7HHg2ymw2UG=^Stv9-=bcKR++IQ%gWrs-*;%CScz{9~#k zk5nu#KM?z&J+2+0A*=gXM_kdTRqYDrv)|5#`EguONvdk$Y1Ea&CFLLiNlPn!*6<4i zKm+1wmEsl2NaUVj3211A8hTfqVp&b9)UGrZ`RZnrLI$-f9%Q#@9^`x@6{x!bpZgzh zW#7zoaIQ`}#?jsQFsY6obO@K0`fRWruL@^R?Z!R4>E-!O_l8!!#$Z2GEM^#Yc%us@YpJvnVO*On;=`NqYBphLhWMGg3~x$^B@B~J;U6XU?E?0bH=pR2c*_rUa2{VmI>Fz$*l0KAqtvg$(a3yi+)+a8k0lXm?lsUZ_3Z8vS zc5lVGX6~F14hew2J;F7r6b3hYHdRrK|SM>c~XB(^ppA>z1UbETtvlhj16A z6w5paY@UzSEbcOBB7}d`?{5a~-mW?5YDs(JpR-o*0lC{I5+~pX9?uuEUX#6*N8hw! zaM|eQxfE{RLJ5j%054>gY{NPa+2jvDbBCEq6FxPWHm&=zeCzmm5f!daby3 zW`Ku&wKBEAO}ou6qOKFFV``*}o2o6)EGjOv$9p+Yrz`7`pW+h^XS-9qKk%-AS}ujZ z9s|xcxbpYEV5d-N&2V`5W_qyUTXa~eZo+D3>kpfq6QUj`TdOE8J_xYfxBF;1I^`Fq z9qbm1ulXU6TT7jtktM66KjSc}>R~NTb}(?Ly(t?Z{&Zox2(b5@Yt}BuaW$!)G_J}> zc5msx!MT-*mD{1%$~*rq>o^1$2q0ni2Gi_FN?YFZZ{$gQ3%2s|6>X7SAOi4@>*#P=?l z&Qi)PY-qzrkV~8E3%kMKN>%_Xo3`bc8@#x~H(g}f`WBXQsef$6&1Kv;(Yk@RzS-(Z zE{_S$U)XqeLv40NhVY4p`ul}4?SnO`u5BoQB=ab%^vHuJZQJ51+KzfN@~|Vu3db>@ zdRuvqr^>_gn$nivTl+#*7JVwWWM~MrTvbTaEN3SIwx_ZqU+l$2cZ(@=b=u?gHr8AA z;rRm~ICz>r<%k=1$N_De)a3{z-CD{EEW7nU)SJy0YsT{G2H?K`!Ryr4E}nk0fXJX( zt=8@!bE`VzNHNjgPo{%j!Wr2n=I21@Q;7-``N;;R#nx0~wkV;ymWhL!P#9WTn3}@I zbx}q8^CW+1EgW}6SJ*S#Qh4rpGLaw~P@DyNLx%TxWFr)}M10D60w|r zY03pm-)r>g>;#VeRo7rz!}#Xv)6ICBm42GjC|`?b4b_XfMDoWU*zAoYsnJHLfOsU> zs1-2b89?pA=n6+Co9KyiwS?pfx1xId0;Ve2(|+c1&2nEYGsC+5aT@u|R-JK&?|0OY zEPvHC$d2+1tRKT!zv1cl_BE>;5S@t3&hA!Nj%1I-SBcAw!c{1>U}=f7M_QrcAl6Je zkYJ2uJ6EM%3MCp}ipPUe)u=Xr!>%-$!M!p00Q=JX1PjFrGQR!=2ofFK*HI*iT^A4S zZMqXb06<*p+&)R&EZk~pDk3I)eJ>v|>?l4H(k<3jjyqwzg^o&99V4&oTys(%FKWG# ziQ`xLq%I|t28i-M;ZrlBUdjXPZ)e^K4>?bDcRy(ffG}Pv?kYqofHER66DOEt#~u!; z>OeL0VBUVFv};v$>d0d$^$CFT*BbvH0Am7?*?o_?@vhSOBi>a$LM|pc!!8;&aS4SQ zHCi=Kl?)BV#!{F9$#Bl;tf%im{f7V{_!qzb!Q%hv1_ESeF(CuMAi*F&2LvR@-U5;Q zwYwluppa34ghWh&XpBOih`*wfu&|OcvnhNh16f}%Agc@v3j70bF&+i8{9SDH@POJwSy@a2WC^nPE$%g1P+|=ifr;2#T8>eK zh8}i)iAIUjn;4woQk*e8;Bp8w> zrBSS(ySqcSgd2tY{nql0`*;Q-tMzD9xr&h|`Fir$$4uOv;$jLlLPPG#BBV&>`m+sG z)L6zwGamr({+>wE`U@oz!WKQ)l#j;X^(}_5OcX*tVa_Q_vG7Ut z_2(Eyq_l49+&Ul9UM#tI8kV`#tn0`~6E(fPxx@x*Aomr|`FklT+ysXi%x6MBm#3V& zP!|8<U>e^e;l4_G0_LYMaJrL0yoK2N=Z+#(trwrTxjY&deF=F-a%K^pHG60 z%+EffMbkP^<`tMZYQxEemUy#f+o*>yYr@B#JNA7u87pF?v~q!=uyVbvZTz%FnN5p@ z#BX3vNwsY>UJKmuH5%W?JUQD?^DdurCOvly{ASTt?2{p0yo|h@$IjpQG&1P*zA%6s z=<7HMxYc0fdbUmGrOQkqc4Bss8vt(LraPysl|M2}%*8f7WR?Gl(7?+#rLgk0^7itP z@EE02Voe6x;UD0*lRrU>wm?{kl1SsV+-7mM2{zq7wvBYxQmE-pNcoV6mo6sO5N6cJ zFTbqq?cEB`z7E9+S$?L&6?9Q%X)OPi;Ynem_3N9SvUHpBk06~y3E~KtEsJrcM#?rH zu>l^#V=Hfl5hUq5+uSoOc?w#K`@r@}F~q2iSX`YP&12om76!E;lTv!48O!^el__}r z`H*j=Y@!xlFo&0mt-O)+y^!=0@PF*{c}W{!skHV3J^c`&f|WoHDPNl84d$g&%3XsdI5t2c$vqZaQ}9^LNnx-%Y(a-=)jOQhE4RY zn#%&o$yDa>uwG%&#iG&ON?BKw7A`O0=6dEg$w|@S7EC$;O)n`b!*mX-D?OTRkJq?| z6AP^|EbZT;_pmq~Y@}!EYpRi@dUg7tCqO4>{IRPeD;vHo@^3S&;>eUV%uYG6@70`$ z4)oe7%E>hKbBS{EM6LbmqfhuXmB~pT0J^kHF4r1f z>ICOC1DN*ylRVbR;s3EyL%0G$&F0Ou0HQ6dI(#JN8=%sQ=(ziTwPKnWf&Vf2p)6N z($Od$21QS?qwfKr9Q1Wkp2ui@f-}=g)6h_rkXLf8vqA3uR4ZXYJhGjQdCRc498l=E zD*XWD7sRlEI^|WRcU=?0hrJeXaGFFUqu!f$kf0dsHj`kVR3U2l_?BF2 z1GNI?FGFMr=(syI$#a_&oes81DZ8|9LvOKj7AZ<+Ge z<}F3_9bK&VSB&tGvp}f@FB!C8nfu$HHGx24!5rdq>Kg98H1nM1Zd=}>oUf8SiEndV7+~7@>%4h8y5OrrPc54En3AEr?xLuaK z1Zf=G4Uximxl=c%~SaML{*^X0T?y$C7u8X(>lXzUvd2hQ%tz07P&S&AL)?2O+x!Xy$1 zfm&JXb$gsL6>R$YXuD-IP7&?=H2owNwl$sn0#q8LRx?-=7i`rc{1m?~f`DkWr_!43 z20Ta(Z9g;k+NEP*Y2+gF#l2nl*MtYd87MnwFG~6j%Jk!|Ad}JEja5$vP(z?445BL_ zzK3iPBsdDM8PpooLOOoFeXy@m@)E; z{8;k?P_Ko-Sk;u|*o4S0SoJ&AVhATcdP-r@QoJ(Y$>Oj2+4Q(@_mVfrf++$j#Fw^w zYU7U0#l*0V$`q1Qx`N~#74+3(Ya)@hgFaXRwfgogpz+tatY1~w4;yMl;NwXMkTs+gZ$*v* z4Gj%77jrm3mdYc9io#p#ylQGkvl{ojMNaCdqpyw3frcjt7RuPz7(U@S4c5C9*XfD; z*Z1(a`lldpdUL;0tf!6joyXg{y1G~lD%$1{wp;Fy1Z+QmFTR;!TBB1jQf10Ng{gSY|9qdO}JkMf~svPX)k>M!PU)qv&? zz_c`)L!%CLeNwteu4J)}g*T5`pAmg>@N7-1i@Mw@x-&FU;VFaSF}qZxU=XF5O3(-3 zu?u7rGok>%Ai$x(A)z4u@vr_jqnL;ZD2PT#%*@E5sP9k0Dx{=fAODX{4DwY9fPoCg z<)8bjdZj{{kvUU&Mojp_f&>q`_&;y^?M_XvC6vC;M(=Sa#q*PxMtYfuXr}?ilW+)a z<7Dk|>8#_-<8)NEC+rr$Ua3f&Y-V>1ul-1ui4fzRfUY9sLcd*fkhdI@^Y9k-WF4WM zaCy*RVaR!#g4uXgt?PR$aubr*ZXTZC_1$X}dr4q|4p)@txHj`^pkk=6;*m6u0Wa(C1fxsyKtwv3nxf^)VT$iJ$R>^QW$Ze*37V_s=; zM=hYB3HRqWMoAP`bY|L&rBzm3cyrQ=f|F5FxKzF#lhV4TguuOwasfs)Ug{iIq-hFW zij5AOSQ-T%1$!#hRxi~FH_9SPWY+K%WNFX~&IT&mV@YM0d07d&7ng}k4L;op_?4X^ zh@`if>?L{?>JB$|aK?Z~h>Kir=f+7)ZwJ7k7G2-PadPd%JKQV6q4-L%cW+IqI9bQH zW@U$nUD=Elg=o0$8*Nc3D2^$36A1^1ZKc|j+m&RXI0@UeXs9gmvBYW2WA7~8PbTmo z`$ZJml)9c5yQc^}SY}Xa7Ut%%lNy+-HcRlAJW@7{vpambt5IvJXd3CBa zrPvm#(^&UJ9fKyH9j-#I>hlcJiSt^ifZwckKhJ)vq_<`eEs_}Hkm6QSb54;-97M+| zOGQy5nSbF(j*3(%Lt1A;N$P5}{Uc8ud3XSBZ|ih|g;Hv!QFs)G+|IKAV3aP&Rogsi zfT!lDxsLFq!G4Ej6MU`XKdf;44e>@zV!rw-r@H{N_%-Q3=4$b)cC{_6IA@VE-?3tC zd)e+{92TbH2Vg;o7jyM%JFTsJ9^DQjCuNo!)t+-y+rw8G4fkd)BsYzj4you>U0na> zPC3lzz1zq+e64F`Bq;OwAVIztq0;i%g3L*pva2$qNoZ$jO?!j9Y^7;fref+7?!<(2 zRfXT6LYTYvKSaLE(!T=RyIk+%`F2%wD>lLT)QUzvH}vx`II(d`NtyrWTcYU1=x=n(j8_C_vgm&BJr}aK;HD&bSfQS1DoO^dv2H4^Kz+~*2PMlGi&@UvLGZg15BOxT^+I? zEvCGrLYF)>Bi}8pP+LEbw0HitI7z-sQ5mmjqK8iHEo-sRkONA7)T8d_@*b!itX5gu z&*M6*$5(YsFyE>~RW(eO?XOSlIR;LAb_CVYHs>svLQ2|tDXvKO zb^ieT^-hqZ0KmaP-U*O${f|%(7&rm)2)U>b_x9VU6AJT^4tKs@d zH0QI1AIzs5#&cg!@>-3CA29@|SGcZR=QHGnWo1niY6q&?*heB*6@fA53kzFo-5J{0 z9%VW>K>qqO)5WRMY^6ua!a>S4!w*2RRaVgzE?fG3)O_>xjL1Vi{%6^-Y*y!j;Hr*D zC5Dw2oOrVhg5!sr&|BZIl!C&kCjrnT`3iDjfrCSTf`A5xfQI_(^!n?%USY zX4JR$k7riufdrC#70Rt;bue&DKvVc0kTJP3Fio4%FJl8$=Ck03ROMx;2ci>ZGQRp zFFOt@QA2~bh-6 z@+<7hP}wZyfJ9l1EaBUwD_(uK6dLrHOS?Z*;SD`7x{K}tZ}T7merjW>v^lbT0~nx45I7gy+?sDfAjGZn4I@aG!70!)@G73sl7~1n1-=L_$s{xL%_|!(~>pq-4+| z;wmn|yi8U1tBfX#U4vTaR7Y8=GH)5pjMN)3&R&;&1vhlUu0j;tSTWUtg5+2yQE6~*()fiG__^4JSaMi3jNX` zJLu{@bH`qEaKiKp6pZzlCo zeoFYb0VswD?I9U?tvPMH9@y^5AWVfAE+Lp%M=ck8m4F7=n+!fzNnk-ga8 zCeNKjorUu*#Pvj1&^IG5{v1Z%fF}J1 zjuld2S(CnYb;I7WDZ+QUiV^lc82IPGy$kYY87o!#>LJ^QnUr`aIts@ixmM?$M_fh; z7$7dq9vww&Qr+kT4Xiqb&vMPTRO0TTYf@7>v%yJFq3Oz-&dQM z!Y5DSR$M@g{3{WK<9KcC=}4l9IH&Qub?z@Oc#@yTrF*I(X}(9m!+V~ z|IRXgVk5k~y95s-gl5jpurlu~=%TZvC#pr1(V23n>Q?;NMAYI);h162nAekAd5gMg z;82fsMu;YUU;Fvz$c7Aq{ROnmH~Iy)P$%|K=dheK*%e3wF{h2E4MEo%sXm>-c^5Om zB3(loTI~MxtfC?E==Hc7xr^A_W*nqCDRfuf-5x9d&y~xV;t5v_u7){{R4F1C>6}WV5 z9y&QraPX3hlpJdFmihrWustxS)u>Sa#c3e`;YLLfoT^tpU&816Db@6;LOX}YpTPH7 zVPPK9Revu2laookX36Aa%SInTKds1talTm4T)t$HkGkAAOaAD-c@IR}Odx8YMIUn; z)OP5K8_}aKjCW$b(BV#7Xzw2s+Gbpl&=p`lQX!N0=aukRQl1Y$TX9om_+=Rf{A8H$ z_e4?fhh5DoxXnHsXndSv0qF`>3zfUV%J~rypDHqOUm{8DJcLk|@fGr$))AA8a1QuU z!MQnkUN#7wdqlRQ2vLG$dmp|Q=zkir2#MrB7Y*0a z30ihxRVDvOtLjg9HcB_K96N+i*%Sml49m&DsIcP|Hap&P17i?nu`Nj@kX4>X^zVq^ z-!MoVb)L!wC*=Rc4*BI<4xUXO*Y@s4acHFq;X00t9{egQyj6lVMQ1VH5&-jCz~n*g z_%k@>#VdEKr*WO6u|rI!U6xry^=mRbJAS)h-CE6g0;>|65w?2n0S#-0kfR~(1EAnN z9~O^sI7eKF=B#WE?Q5r+hfcmuE6>f8C`P6NTD3a^FbY=`=Rxcb+*fCH$AOn+%@Wc5 zs}f3KE4R8_j+?RrlKwJjbJV6>9BhiwbRqo5!iJy8By{g~U5BTj_f;hV#GUJQ(f83C zkm@>uzaRK(pa=BRj?U;=XqHVf!wKe<^^6}EtUC%&sP4tj$YZ!SJzW+ssatoQqiv9B zsp`8Yt05)Fi@s0Qd9_eio15?5&P7;UPpF#osj9IyU+dnj+VaaJg^sI+b#E7gErceO z)naS8y{4?SLQxtN<1TbJC*k4#X*@|U|D3RQm#jOzGXVTN_~jBapn0K8Y%h1ynv*Ui zaYD)g8|pfz`KCvHmH6HwiBiAax7ipa+HDtOz|8kobto>u`hpX?z+;O~+Sz^W2O!rc zMc}=zOPb&X_Kno{nC3pdE2q38i}1KQz@wS2xn^zj;fAdV}b@5 z05XTcVE$%C{V#(U4CSwtgZ$UXsqMKY%w?R}`Ff-9{XgP#0z{xV-Fh!lxWzHt*hDM} zF9~+^s=!JxqU}nMTN_-f?!7yGiN)1&3h5WiI`w#qZ%MN!ihBq_vtFs8CSBL{x9fbC z=h{nC2SO;tNQTSvc`ZDuf=u+8@RZiSnQKZ(Ezdh+6~!8Xa$Dy@(n6R*W9s^|K!R<5 zxZDdvtkEqQRNSmL==jS5!?*z&*(Qc5+=0T>LbmsGW0|(xlu`w(LDK_>;Ktf0!!Jsn zVV+biuxHBEBe|xq71eaU6QpKetTD#{hFCK$ammm0;vax747dFsfc?hs?+!J5QHEH9 zq$LKpv-$~!Ut|@FxVX`CAI7yLBb4>_)G@744<(bTn;=pL#T6?(R3vhOmwJ6d?!(4y zP*Iw<6NugoJ^%scG-0__4*n+_CuG7I9;8fBhWG>KG9s?A#Osrto;$h~bFWmkP1Ebl z-+*Yic@+|)DdrY#6ixXMAPr3!)EF{bM48(!%L8vE;~A8SO%qLp7Fq3~Gc zHuPx?iC;}77cslF%XADvi{j>jbI8n81`>M;o08InNqnKd90lhL=ZCf5&)l-h#%SL) zlW~?gJGClgWMtxL1<71SDh;!V0u1N%{6g=?#&-EKq@|@NzKx9|PA6HZW#INLTLzI+ zuWRou_TgZEeFrOTVJh0iPtS_(G(`|akiy(Gv5QY^qr(UQ0!dv2F|FLPKUGoaWSr&X zjhWMs6&97~Xo}=jSjZ^EJCt8ie)~BlVm5uSrbY&nmgdz)msl$)xmAm*&jm@eeLX$M zl+0$_$et@|6Us28ed=t09K=Ipw*rH$-oHu5Cj2&UK(9?EDzr+pVnnTU%@Y@=r6xS_C7Oq+!hoNZCyHQOS+iG@Ai4<< zM1-!EtVIX^i;6#vFY??hr}VXc+geh`_SU9qfuF(+oG?NteF_a8u%m}231cXvSR#{a z>k%kdA(QY^M2|=%^#9T8ri#>03NH+8c!Bk?=e4JMN?Er#gOJ8fqCg>u@5VX?jfW+M zSRm@Hv5k z_JfftrvA$5QGQqje6=QjAgJ@U3>2}=e>4gQCdig@p#!(kc)c%ik4!?h%+$biiLmYF z*_@c7lAYFNi_-08EU#NB-`^S0zBpn95n=cxM)s)gA6yRSk|v|#7#(-Tb#(;s1sWw; z_|&0rH(by6q#g1i{ z=K+!P&m|G67qp7vv)5fM58C4JJg2L8#V;Rz)=mMXTOt?{>eKZ?10t1Uz1dx0K)rN} zMBNka`~i2oTf(D610PW=NjK>C>ClAT2`$fxAqNXSqiBo7C2fNS8vL>L#O#KEs?k?P zR2a4>jhIdO%^R-ZLI}mG-Ie_%^8t@t+h5d&@#7VY>D^_dA<=jtv}sX=>s6*cqw<) zeTw!V!Z=4hA<0m1RS;m$%+CCdKq0(R4LC!Cshk-^SADxEY!6}zM%g8 zfr!dVl22&3@-=N2v6B1d`!c z65B-VTE-DtBqH?@xEwQp!B{%t1OcPpe+G~{sTdwKW{O=Dyorq`A z{Qlsb`u6t?*u{RN?<+AnK+5_rw#0`}d=HRzJgDJN#v@hI5bV!g&g= z314aw(2elVK_mP?rl7j)O~a;&z%?wioP_RljRK13f2SLob7tUe=OeR<#Xl zQWiryK2;H(^EVM8VpzwZ_011ZrYdr?>nZiWOhuQQ8u>@cvhEaL8$qM$q!zCuTd5%% zjbF3Iv#|L`-}#F%_*tLl2hpt&Umkk|QT8#|UuzEY(CbVsYb;T<1F0;~v5A1=^{>eY z*IC2#7=7r>lJkRFhz+PUba^K=nc-VTVTDex{CkGFGcwzyJFf%?pZ7X_>#rS@PNt>S zVx*lk6@mB*b(WD!GsxA13Nsp>FeKPGv}4Nm^oT$FRjQ;kLwmAfp#A!OI6mU}<6Y+% zNj48Mo;59-F|MN;Xyk?w77`~jKcRW*NA^m|zRdI)N|qSr4#Iv>?`krxGf;?S_d#D8 z+Hijwg9v`$-~OR$8b;b0_Pw0UT&UVU=KOd8e?Z4y?<;EI{rt4GwRS1cal6SM%j=7; z0MyUGx`QpF^G~lZA*!CWiBK4=_-;s0`H$pg*cK*+@ zFIwCQ;C5}X$5PoaYOsgZ(VtT?HQpSt?)W8PPm)+AzZW+sOv~4Q&n#Iqibr^ZqFQE7 za3x}qc0bFtg&7N^e+ZZqd~)S$iRpg-Jo6`oJKVabD5>=8B_e7xlJ0d0hJ&%w^zepk z^RGS8yyfW};$p+2>qX_v{wlqUQKzAqv>-mc$qxXA=x7t&t2x_`)UI_}Sm=cG9zIEG zR^*=zP-?ds4kTvDQSQHa{N1m;Q9^rucy!P2V`uUtUbNfz#q(#ZupzunCj^%k+lK(^ z16-->S98Bu#RU;jL7uW(8vGQ=NIB>V;W(tg+RT77OE4q7A1KH+iKA6ARQYnywsXfZkamHrEWm69?NfRB)c4OxfYn|(a=t{o9;+-tqF(N421r;PHq-2M3XJw<3=PnBxt`F3V$jc7RSJlXD z=K;IA6O#4OjH2>_v57(<*)Z%O@Dx`i4~VVN*V-GvWkMLfVT*dB+@SG zV@b62X?OP$^S%A(K|0QgT*l~T;ym8mCV$*{6~6~sB%L~w8}8QBI^j|$onX7QIf9vy zKSC-Gg!8!(20funzm)WhLTG$2Hw|PpWfj?s6jU; zl9&rpmGMWJbQILux+eC=b&!VcYy`fPijJ+W$vfo(kI5>Gq>C&8E>uY0t zQ?vOzfC4VXhXrE8b2o1I_Mj zt-*WAjYcA-#sC^q$dEM{dy^tZnziCSfx-k85P|J-+Xr+M=!m11n+?& zn%ieS++@)^Q8Y)rT!HD@MJQYDnIgu}QPUbR-kTSk&}jVh&&JRU_M?6o9TZepl(Y-m zVJ+*^Q7Uvn(&cD0zWYK%$YEN@zdiuFzM#L{|7=Y9XHORL-4yTt@z^`+XyZdmxNiT? zTCpOFYaxcD2kCVAe@Q;csc>EA{Q4x1A@M`vpJsr8nHBCS;IQcjz)qB!+ZWUh2?J^> zU!!!iSJUzP)JfVis2zW=J1IIWxiB>EZwR!Vlc_0QIROPqPKTO8vtY}f@89tq3B2x( z+8`P=lGrSX18ENR3qJs3ig$e+)Ph+sTDcPlF0A>mc>w?=2tkt29hq>%<|V1Hgm+)o0k3nfMkQ!P1xo2n)5O}cCq-9W&2mEH{#$hRM&xgi2C)H__6=W znYIi$fEMx#NpB{!z`rHDcl`<^8NIZ$LAL+n=c8r(&s&feh8hJFU;+b&ga-U|!~7d? z`s;;3Rg09ip~61 zzRS%S?D)^#rY`l3K+DhVfbA(x16-KVVWDAByar|bA&Ij|9szrYK+~6UF%!iU4I9v| zsXAjMHIlsW2|b2e9vbxCs(5aAa>_kS>_w|fCu3o@qM?)PcfaB^3AT;xwd<^kicjs5 zbHAm|SUDXSea_%X0CkayaEj}qX5E#|d+_?-os*+=V@>6a@t%R^;2q*BTK*Uo}fSg-%^j#Q^zT7k3#=G-Mr!Y|YO-|arn zPuC=9%+V53e&fGpBB)XzG`~r6sG3c%;>jH$ARlu~0UcXjIlcz{3M2p7>3d7B#fTf* zlC?Wr8xuvgT(>H_^=l<&?(ZwgVa&1(3uBk019aCqSHA(7 zeC)PcyT`o=i!SXRNF6YrPTNt+Ci^*Ca|7&}$4^9`^c!%5w|(*w3St~?Bf+$yhrqg! znkfm*ei&m#L*ubOrk}$Tar3e+e?CK3E24-f@ffFq7k0K>dH*Ad8v1RkfK-Zx2EEK~ z!o^i!xTMZ=Alaz$vBqNU@dTn|j5ffM2_bNmrb0SB^?p0&Y2oFl9hLW;1xglq_5%-(*IqHVY4$2R%K`jj|jH~2nAn{wC*Vu)2?mVJT@Su8RE41@`%Iw*=Yp}x} zt;dpD+&1kGAp(qF$04fGJX=_nliymvh^%*+o4lqr*$J2-ko^X;2o_6e?%b=k26JzD zMwG#|dJVPbP32pBhk>wK%E4=PoGm>y42HkA|MPegT_2O-DaPK1 zW4Z%JUw1lhY0fpIYduxC-i!l2iw_B zqqFP9*Gzmu86v|cFoZ(d8;6i-=+Zb?8>zh=9%cv0+VHZsxpOGxLT^%|&}~h}fDwY& z))TN<xXrXhv3uxbWZpInB`|D`w1?zJ#u{f16lUOh zKKoQDXxEFb)#Fj!6vdV&O3S|O?0nC3I7Yg{ef3JGv$yWbdF5%E$SSFO6x1L0)e;DZ zW+6sIYr9D~;rJ4WtlbM=6{I6+`OrJKWd3_PrHvNP)z=mml;j{O$&NCAX`iEmH{vXP z_*M)|5*jRwDD{+d;$bncfZka|n0PA~KrEKDJHroUSgn0b@gIH{)J@PFN048$x0@$c z`<61tp+7!OcnE)p+YOIw^JP%)^XQbj9C3*sjZCrKr@*Gjy&HDub@w;luaE^HnaL*) zuT*`kEw|~;yvrA_Qy8jM#!_tE-=n2{Jw;@|{@^aZ|6t(nnrEYGtNnch*8bXbzh{C^ zD+ePLUJczfa|I<_Se(&5N1o(P((@eY&II3922Tp$gMjSv%tspH*g7Q~+{@uy@ANzd404T^HHA<++sILHW zXYc%@KK~|mfYc{=*xPdU*^gTRP4javSkVis82EP+zq`QrVHZxc+n&BAQ21_S9qR*t zOcUg3zbePUB_=+Lgo28}Ddl=}^@O7TCBfclM{5Y`r@Lq7;0X#T^n3L%N8Z%ih!L;~ z$zaVo>{2$^LwxC6BnG{D=xmSVv+5;x>Z1V4m|bGk1s%!d?|`$-?0`5w#ytp%%AZUG zk?suO7GGJnt$A;bwh|vmfzXgX@a5&_{<#<-%?$VSj-OMoytC@f0deUlVC|CGwfj=ahxniWfCYn4= zv{u)MYuJwHf7_FYw471;hmP|PE+pTNtbUD>Hm>e{aF^h{m20L1JfFfva#P~6sW0oA z?%0n#8~ZV0^+<+2zpGRrh2=Pytj>n2#>N*5zI_?P|;yOkCnm#}WUlW@h|aQ)T8gp@^;?aQRI4 zOLU&F#cRE^o#(I%x2;0p11?IhkDj~;1Y9}oDWll9`zzx434V6Z1MsE(kMtYUz2WIv zw`9+?zwiU^JO7Vb4>|EW$j1|&dXKIohZj$QL0wjY6JP7MN8Q-B&XldU@?~HDe_|_t z-|7(HpCJC@wGNt(e`729_Q-!<>eqxlGmKwvcK%yz1vD=ovwSeH2m7#NbQ2K@=1Z>> z*vvKq@5e4!^ws!!ZuQm$t(+yIy$6H8=zzAD5O;!^yl^h!RSAzY{gST67`=z-S*0_$ zqJ8-+!^)tXqfjktBB_)84(o5J49^eY^CCD`(n3(0`x~2&q&l#`5K6a=mq}Ae3??p4 zkke4YRMI<#AO2f>Rp@?F%%L8(?>Y2LH~u`%25rR^_&N5WQ4kOkwCD%z~{ ziXw{*T4W}wkpJ0JXwx&@fv7#to@bT6m^Ifed`(^>ndH}3_?*O@^$FBpEPXS8YhhakY3TTW>UV8qqY+V?B7wR#v#k^o(<*^tA2L zq?`w5cE>kxUt_0F&;p*-Iz>f*iOonNXq%^*FBpAGT5V5Z-YOgVMGwAVczm|I-|vZ@ zg8r`nHyFt0%esnDnmrA~dTSnu;tX7{zR;sdOc28iFiT*lp!j(r+ha#z$rRVMEtPV0 zZ8Ul?!sW9L&rur@$d&$er^5<~ro)%{9lNbpFMz<5nn9ti=MjYn>g`H9n6)(3@PBW# zZN5!MD15M0gDxj`L*5%rbv}+gqC%KBFnUH_v1zPvO4F>c(o)t~ymnPzfsZbng}(r4xhZ}T#^`Jf(VA^4(pOR3tAco5k)P-_1D)&WTk79>L$qH zA=~`DrZ<}g!P`#7RIIH#vYovC>_Dx-RD3wTZ!O7tsB_v9k}7;QQ3nC8EgLlNMQUW z@rOro<}V98feNZubv_~Jn07F$8gAULu&x;tLoy+%`_7bCwa~;vp zC06?rOzy{k^4`QOZ3rx9nbJhP-|x(OC6W0#KL{oy-DuH-6(_6+ty&?uI3J^4Z4Cr+ zB+GB`){>S^-{BmDwOwY=i^d2gr+W#Wuhi@QC86k)-jCC-5D)+YfG`rtPAUbH2zkM$ zrO$3Qpjevqg1AoEitST;LC9~K{6c_hY&-eHpd1^2P@oGaqLlfIjg63EF>r-~gxr88 z!5f@$D=E0lX9L@qb5KCQ^_#*XGQVdeLtk_AN8!vA9DZ(*5u~J-0c4d+TXWr!IAN#w zR10*PzhREb`Dl6b6j4P4!CEj7*HNu<>(gjF9CQu~_g(a*W+m@5b%-qKxhSTm%q<-% zWU@s!L3LhGwPi-%R!~6WCbECwH>Y=^YgV5OC9d%Xh=dPprHx8SU$E-G8H|;L2#>RE3v2IePM}&gPb{s;@ zlWDDQHx^(93ivZq+3?Lijb?M-*}^}kg!X>~UdViS4Ng9A5mL4!Ed<-MTsVlOOEJFx z0LbvySpNXT0#xffbePrd{Y-ZO%PGYGKnAjA4H|MhFAn~@O1%*(pB%w1!jff5w0R<4 zveus6mY(+M1VK0a#}SoH0BW&kVrX3spWf>fUIiZ;v<_QN=i|J43xv>G9h$yJF*nU= zH_Xo-PO~O(!mHbUu(W6}0gg}HG(7%b$7As|{p`&jMq`HkXTp7siS51#@k`m`;`u%p zpO?;9ai?RnEFi@iHlztk!KY}@P#mC9P+s~z@Pq?KVyciF+FNga=6jgq@tiUHjp2sK zbwFeQW1C8Eo8nP_iM?x5HgG@{3I|Bj>HDA8%+c8VL!Z5vvGis*PRpy|KF>s6kHbDV9?pJ_ z?}jZ7{{T7dUl2Vnk`AI%9w~xB%{r4Gruy}apU`2!1PTXq$frn&bUkYI<}CekSN7yyqiaw!T&iKD@)QYKw?KYimiMTxU6{3tXDhov7c#)vN+^or_b z@{Ty7g7v1iTLaChV^1;Ex9VE+lt={tP(Vs?)>2mEqs%68t309alnOPB*_7`Ii87Q9 ztxS1zgW1$r7&qzi#*lD({LMX&!!`MS7;nq+pHOHHeeg=%tLtj4!WGhFknW*4mvHqaZ4eKnb(%@2_OxK4d=L*q6%4@HH709v{kfcRvVw4L(q{n2XW*gd)( z3=!9Wa+O5jcm|O)V7Dm_h8|6xQo1;pV>oYqx2x9QiKx(!!V3|h_5nx8c7}7w;^`ST zMBa=O*55dzjs%6E4y-Mb%(S*0e`E>3EpJ6!;$LVDQuuJfEkF+Rq2|=2U16qTTQEi) z(V7MUl2~bt_BlY2Q&t_)z^pSl4dxm3!Nrb;qd(*`Ov?w9SS*Rv z)IOE?SzA!`{{WF7nvIcr#;`P@MzS4}M zvZe<*v@q2!7iM1snc!L-g{1QjIB7acDI6MN-dIb9u$(z2RtZ-Uq=34>m;u*^FEPPZ z3teJRtNtXj*!W}LAM_%6Ff%aBu-U+GpuSL=x?@lqq0cLp7h)eoXGv#xb7`Mk)nmnny4T3Jb`uhwxSny^QzWNY-rin5(w6^9;2qhbW&-V~HwDk<@9tdf*$v9IzbI7YjDf z(lKpdMuW-c&i(bXSa?qp=3zw@qk=gGD==&#v3zMw*^>^y(y_OLtQ5gP&}bVA)4uC4 z^dYJk>R*L#0~Tje*BFikE1<915EaC&Rwcu3NN1O9)`BWTwYg4iyCIq(93I5NX0}X1V1!cdHo<9Gh-qTAN{A|W4dRPaN>_L_LDP^Q z)TWu+m>P3A7?%rFJpuiGE}5gBH}*m7r4KyUKK6F-@q1}pG4m% z1UGBcpWH3qlNuRrr~bsi6;P^TG0_*H{lf?_>{K-&Olif$y*wqp4CaN6ye^nTA80x- z#5st~Wddx9LsXbPaA!7bRGeo3@Br+R^X@yfs+m*(HLBHAeSx;rk%Aw>u6@n_a$52h<~Fjb^M?9j(;&%p4RV6bh(JJK^^38d&l zrz+f+3Y!k~sDgH((3LAktPutAzFYS(x7m~d(M+a^(goF2-j@x80R~7+N*%8NBDpQ} zMMoqFWhPakhtKf}1zNpk!HpC>VE8Iuz*S;XqYV!Tk+ah=tUq041MTk&R+fQfe&%Sr zA8P%0TxFr#E-jBV+`o7&=L;XA!6OS@vQM?owa>NBrN(b;7j-@03tVGV8CW{NEmHv2 z9{6tY7DuFLp#&8)2JnTFhTSJw=`N@-D`+M1{B?IF?qYlzhM;??{V~S^x;jRc+&N|J zRb}PA20DV7okR5p1nSV0_zT)4)j;MdQim7RV$7s~nUp9oM%2uS(V4Mv4H>u~2H;IZ zY<-{rVp!Dr3G@@_CPq6g)%;B$PLpv*G-DaK$xOc^QmWe_0%be~3LLTAq;QwCdfFh= z#Y35@A?`npAVWLR`?yZ+UStVzn9~K#-G26isv{T?%Ws9$Jd%CBYB^}sI8^+su@E<< zGMKl{$NtSViskPxoqQGkrNGB_P)mrHSXF8)j`V~CLUcj2O)nyuUz6fe=thVcX$$g# z@~d|7hIUOHpUH}xR!|gojB8o#;g~3rI^hLhS8>yz==yt3DO!S z0&%+)xkL>&hL$yhV^)Rg1N|m9!KWvSjw+?AK>g0M?iNt;Dra@w%|q{KVDJRRC`&R_ zSOy}I8btg7v=%fRf$2!QkT&kRdxR}oDb<)&WwI(&IMri2Q+`{b!( zO*9}5B|E|Hb~Yc|!T$hac?%Y+7OZ}2E_rT!o|t_Pfdl7!647?~!pTe8P`yH|Md2cr zQFZdZy<2b0=R{0GCP-5o!r-Y}7^*m&vKzV2TBFKtnc0lW_+O65g#=3kAsmSncB60ZBIkX@MY*q;TwRW8Sf(0>q#1c3DV6x zrDUak&<8tZSSca`28h|B_dX-;;Mu4nDZD{bCPi=tt1rB(x@FVVg68*n8y#yxaEzM*8Rp7&xS`<=hk8|6!QH4XNzf-A(0A>jX zFh>NdJVm`O4-J2waNMGn!JI>GdAYA3rE^*-n`&(KuLeP4Qbk!WDl&M0OQE;52bsr$ zUx^oV%l9na{BdcU`=3?#Xhb+*P-RT6q)_S6DvhQtU*P6-de5)vGqBYClD4i^l)JSHa`lw zpes7Xb#i(BG-m*08K-zCl&E##e6{j`NCgnyDz67KNO{BOR#amLOQV#kl8Gkz{fL>6 zDX?0HwYeASZ#7Pjj9#C@JUjdn^z?%Ckht>s zvcAhE3UW(=9AweM4lZj^rmUm@9n!@=rx2Y3RsoCb{ls$0ss!?bRYsQI)1(FjB@t9~ ziEj}v&LO&9dqC3$J97OVQ6u4EAz)fEm!Qk2qteJQe1LgIwy0-uI)NYS@ueh0v!pl< z&7NP5i<3r%DJqZp6Z<7x|%K&V@Irf||0fT|=j-N4G zGWJ~yO$cx&0=B(ng0e}vAoUu(-))hiyyrcFC;xL53%xL=%UT_ z)?OTZ3}1J23@wT)i(-@t=J%G0SF9XRx9=R8fo(cmYZwTwla<|CE&l+HhlC?8xN_xM zCT3%W7GIr*ksWu@BO*Q8^Fu(`ug4f8oDnQXTO$-`*qWMmtsbK{@mY>AVad#Kr;%9x z4*pSycBiajZFJ%wA3@As^cW6aBY|C@(q$YC2BbFiv9nhf)A^$GJ}h{9K2d%B<^8?l z`*_cx;FuqJCWJi?7eBpNK9pIHtzZRO{>e%;$$HqVPz)|PhB!w@h@#QFFr!d8J|P3K zDp)d%8z1kC2~Y%v#0Yn7-{l=nrKXUadVykA#& z^gLqvcqiNFmxpM28Xs@w!y}|+iY&8jGU4kFedA3AB2{iN>ny!uK3ygS?Q+whczFK+ z$O5Y`KrP#>*3i@U9Qs74+eg3<&1PD+LAv%L!AD=wmU~pB$hEd9XLkYK8>axE7y#Ib z`LvO+2Q*(Yc5W-Hj)0rB4K)TKUXLnc^GDb5`o>1mX(3a9N3sZGzM9F zTWh>rpiZ$PHdjWM2UdbLriKx5*&4FA(jh|D&Ne|z7|%TjBVh08fDu}-3)cvOzzaCX zQ>=DkObocc?8UPkdzbdbS+#l-1ZPm@JF%(mW)*6~C+=WdCZowOgVh1Jx8^SvQR{qn zitgA0gRnu##Qy+hv@zzT#vPk2w||7CXf0(sl&=2(z-!fi!@S2BJ3A*)%tjXOx*tLJ z4WEm%6{##^M!~5RP$6f25AWBQCZfw7Mn0%u4I(gQ(kS)b&?szWmno})F)SP004xUY zB{h5Zif+7+;gOyZVbicjK%|*Hh+S)Sm#j5wN8Eyuui%VC87SG@nkNZlXDtU8A4#wX zy-gt7xArT%w3-ef)&tfxIUt9z@KfTcvBGvY?Jr-+820>NJ|5?@{z_OXlTHstv+EVx zm9zWrzv6--2<*kNS-%LINOTj)H9fXlr8(Lj+w8Cw+3vV@MSFO^zbV(tMFs zxtR{|$mu-HxV0LT_dbzRImzoW^SJG|^U6JZ;w`z=-)AunL|hv3((>jbCiQK;zsUab zo=`6gBsNRm)1Mji8r8S{Fg*`O0vCG!0FP-@vZI5M$4BVD z;5{hWKPuQe=N3-#%I+`0 z9eE|j>LB!|^&WT{eC1_RP8dOx7YB|9TA}BpG6$3RYxRjNawYj%8X{mOdT0 z;M0<8O#wom>fnguj0LC6@f0{)LwLb}{spK)R1j$!wfZ(F{{T0XXku$r6KAgvmYP#_ z0Z9HxB_)xWcH?PdR*Q*(>nvtGw16(XVe5!nSaSnhEEFdPG0oQVARVQ{L;yR~&UQ)# zZPz^|P<6mu#P7P>?fZj-r#*WOec=@N0bn|PcAap-n6>b3YQw|eb)c#T@rLWfIQqLh zldIEc#15@MZmj@zbu8aR~`LkFcir%vqDRjzW}UxeLR)}2}3 z9*vMKWw{$cX6l-{80!p$@00fh88`~-!RjjXI_U={x!mPQc{muWw6XH2Cz_#S&r$VYEcee*Bc z@W1x787ilfFCQ#e+s;k-065xJO0}0Y!s^)Ab&i6yARAH23OW$C_Hyl}9foUs!**!eSvQ zoY(*zEWI4LBBB!Y6upt!T$i_KmXZ^Wua{V literal 0 HcmV?d00001 diff --git a/public/images/network/darwinia.png b/public/images/network/darwinia.png new file mode 100644 index 0000000000000000000000000000000000000000..874eb2960a0aa19ae95d6062cb3a85425ba9ba9a GIT binary patch literal 1099 zcmV-R1ho5!P)vp z!TT&wJOUEJ5gJsy6_f}!0t#{?K#<-VF+d~IIY{aI8{C=hWMg-h?&F&@X_|cceedne z+cy(2Dcaor9I>~jEglJ{2klsuKrd5i>I z=u`;FkW)cHd@8za#1wqGnn$dB`@-t3W}SU`%FduT;C9X*3d3X))ko#8vp)c^@|7uo zjE^|mUe(IW{Pmh#0pPhZ2N-5pIrpMtr=M)Fz}1{wnYv)h05E?A0BI(+><^l#eB}V( zGL}Lxt_r4HV7&~|Wsq|#?-E-ateMr7^tK~DyRCk1a+k|KfVErA0M#N_eF{1 z3`mF3xXI^g4*arIH<$n>Lko67sLH7L&^%&!B<<=Dl5M+ArE=d&-uJS+#)) z<{+pL-TUqtp8hn#*6Moj@7!P4gtpYsy|8>*-6Kl>^@7?cHuUq z;)zvACQ}O&siV&}q`#xmfXqd#$mTl;0I%Jq6jhscF$;^1c>1jk)~F)fitWk&huyyb zFyg+)8+6dRlUg&1P&!>)V?rY99ulv%@qSxt^xaMY|Cb7^tOF~#FAMR*)p4O9Y6x)v z)<{yPkC(m|vOu4%v$iav9iyYOf?H$#dZi6MjD*DLqrzZ71o~lwe&nGatmwx#`XP~i6r~?{>BnmN;hla(K);AE zDjLX$rofAvI*AY%r@k~swAQ)lO8BpB=$BoTD>YPCYT + + + + \ No newline at end of file diff --git a/src/app/globals.css b/src/app/globals.css index 26e1882..e77b20f 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -28,7 +28,7 @@ body { @layer components { .border-radius { - @apply rounded-lg; + @apply rounded-2xl; } .app-header { diff --git a/src/app/layout.tsx b/src/app/layout.tsx index a1817de..fe3c319 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -10,8 +10,8 @@ import TransferProvider from "@/providers/transfer-provider"; const inter = Inter({ subsets: ["latin"] }); export const metadata: Metadata = { - title: "Darwinia Cross-Chain", - description: "Darwinia USDT Cross-Chain", + title: "Asset Hub Bridge - Darwinia", + description: "Assets cross-chain between Darwinia and Asset Hub.", }; export default function RootLayout({ children }: { children: React.ReactNode }) { diff --git a/src/components/address-input.tsx b/src/components/address-input.tsx index 58b6223..d897796 100644 --- a/src/components/address-input.tsx +++ b/src/components/address-input.tsx @@ -71,7 +71,7 @@ export default function AddressInput({ clickable={!!options?.length || !canInput} canInput={canInput} innerSuffix={} - wrapClassName={`h-10 bg-transparent flex items-center justify-between p-1 border border-radius transition-colors duration-200 ${ + wrapClassName={`h-12 bg-transparent flex items-center justify-between p-1 border border-radius transition-colors duration-200 ${ value?.valid === false ? "border-alert" : "border-transparent" }`} inputClassName="w-full border-radius h-full bg-transparent px-1" @@ -100,8 +100,8 @@ export default function AddressInput({ )) ) : ( -
- No data +
+ No data
)} diff --git a/src/components/asset-select.tsx b/src/components/asset-select.tsx index 07b118a..ecd742e 100644 --- a/src/components/asset-select.tsx +++ b/src/components/asset-select.tsx @@ -14,30 +14,31 @@ export default function AssetSelect({ value, options, disabled, onChange = () => return ( diff --git a/src/components/balance-input.tsx b/src/components/balance-input.tsx index f2e4a0b..4adc5ff 100644 --- a/src/components/balance-input.tsx +++ b/src/components/balance-input.tsx @@ -1,4 +1,4 @@ -import { Asset } from "@/types"; +import { Asset, Cross } from "@/types"; import Input from "@/ui/input"; import { BN, BN_ZERO, bnToBn } from "@polkadot/util"; import AssetSelect from "./asset-select"; @@ -18,7 +18,7 @@ interface Props { disabled?: boolean; placeholder?: string; balance?: BN; - min?: BN; + cross?: Cross; asset?: Asset; assetSupply?: BN; assetLimit?: BN; @@ -32,7 +32,7 @@ export default function BalanceInput({ disabled, placeholder, balance, - min, + cross, asset, assetSupply, assetLimit, @@ -52,6 +52,13 @@ export default function BalanceInput({ return placeholder ?? "Enter an amount"; }, [balance, asset, placeholder]); + const min = useMemo(() => { + if (cross && cross.fee.asset.native) { + return cross.fee.amount; + } + return undefined; + }, [cross]); + const handleInputChange = useCallback>( (e) => { if (e.target.value) { @@ -77,9 +84,7 @@ export default function BalanceInput({ const inputWidth = inputRef.current?.clientWidth || 1; const spanWidth = spanRef.current?.clientWidth || 0; const percent = (spanWidth / inputWidth) * 100; - if (percent < 10) { - setDynamicStyle("text-[3rem] font-extralight"); - } else if (percent < 20) { + if (percent < 20) { setDynamicStyle("text-[2.25rem] font-light"); } else if (percent < 30) { setDynamicStyle("text-[1.875rem] font-light"); diff --git a/src/components/chain-select.tsx b/src/components/chain-select.tsx index a601da7..1774708 100644 --- a/src/components/chain-select.tsx +++ b/src/components/chain-select.tsx @@ -15,30 +15,31 @@ export default function ChainSelect({ value, options, disabled, onChange = () => diff --git a/src/components/transfer.tsx b/src/components/transfer.tsx index 48d7ea5..9d777b1 100644 --- a/src/components/transfer.tsx +++ b/src/components/transfer.tsx @@ -4,7 +4,7 @@ import Button from "@/ui/button"; import BalanceInput from "./balance-input"; import ChainSelect from "./chain-select"; import TransferSection from "./transfer-section"; -import { isAssetExcess, parseCross } from "@/utils"; +import { formatBalance, isAssetExcess, parseCross } from "@/utils"; import { useTalisman, useTransfer } from "@/hooks"; import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import SwitchCross from "./switch-cross"; @@ -13,6 +13,7 @@ import { useAccount, useNetwork, useSwitchNetwork } from "wagmi"; import { Asset, ChainConfig, WalletID } from "@/types"; import { BN_ZERO } from "@polkadot/util"; import notification from "@/ui/notification"; +import Image from "next/image"; const { defaultSourceChainOptions, @@ -33,6 +34,7 @@ export default function Transfer() { targetChain, sourceAsset, targetAsset, + usdtBalance, sourceBalance, targetBalance, transferAmount, @@ -76,6 +78,23 @@ export default function Transfer() { [chain, sourceChain, activeSenderWallet], ); + const alert = useMemo(() => { + const fee = bridgeInstance?.getCrossInfo()?.fee; + const balance = usdtBalance?.asset.value; + + if (fee && balance && fee.amount.gt(balance)) { + return ( +
+ Warning + {`You need at least ${formatBalance(fee.amount, fee.asset.decimals)} ${ + fee.asset.symbol + } in your account to cover cross-chain fees.`} +
+ ); + } + return null; + }, [bridgeInstance, usdtBalance?.asset.value]); + const sourceChainRef = useRef(sourceChain); const targetChainRef = useRef(targetChain); const sourceAssetRef = useRef(sourceAsset); @@ -219,7 +238,7 @@ export default function Transfer() { : []; return ( -
+
{/* From */} {/* Send */} - + + {alert}
); } diff --git a/src/config/chains/assethub-polkadot-chain.ts b/src/config/chains/assethub-polkadot-chain.ts new file mode 100644 index 0000000..ece7e54 --- /dev/null +++ b/src/config/chains/assethub-polkadot-chain.ts @@ -0,0 +1,75 @@ +import { ChainConfig, ChainID, ParachainID, WalletID } from "@/types"; +import { bnToBn } from "@polkadot/util"; + +export const assethubPolkadotChain: ChainConfig = { + /** + * Chain + */ + id: ChainID.INVALID, + network: "assethub-polkadot", + name: "Polkadot AssetHub", + nativeCurrency: { + name: "DOT", + symbol: "DOT", + decimals: 10, + }, + rpcUrls: { + default: { + http: [], + webSocket: [], + }, + public: { + http: [], + webSocket: [], + }, + }, + blockExplorers: { + default: { + name: "Subscan", + url: "https://assethub-polkadot.subscan.io", + }, + }, + + /** + * Custom + */ + logo: "asset-hub.svg", + assets: [ + { + icon: "usdt.svg", + id: 1984, + name: "Tether USD", + symbol: "USDT", + decimals: 6, + cross: [ + { + isReserve: true, + target: { network: "darwinia", symbol: "ahUSDT" }, + fee: { amount: bnToBn(20000), asset: { id: 1984, decimals: 6, symbol: "USDT", native: true } }, // 0.02 USDT + }, + ], + }, + { + icon: "pink.jpg", + id: 23, + name: "PINK", + symbol: "PINK", + decimals: 10, + cross: [ + { + isReserve: true, + target: { network: "darwinia", symbol: "ahPINK" }, + fee: { amount: bnToBn(20000), asset: { id: 1984, decimals: 6, symbol: "USDT", native: false } }, // 0.02 USDT + }, + ], + }, + ], + wallets: [WalletID.TALISMAN], + addressType: "substrate", + + /** + * Substrate + */ + endpoint: "wss://polkadot-asset-hub-rpc.polkadot.io", + parachainId: ParachainID.ASSETHUB_POLKADOT, +}; diff --git a/src/config/chains/assethub-rococo-chain.ts b/src/config/chains/assethub-rococo-chain.ts index 8eec5d3..2bdd097 100644 --- a/src/config/chains/assethub-rococo-chain.ts +++ b/src/config/chains/assethub-rococo-chain.ts @@ -1,4 +1,4 @@ -import { ChainConfig, ChainID, WalletID } from "@/types"; +import { ChainConfig, ChainID, ParachainID, WalletID } from "@/types"; import { bnToBn } from "@polkadot/util"; export const assethubRococoChain: ChainConfig = { @@ -42,16 +42,21 @@ export const assethubRococoChain: ChainConfig = { name: "Tether USD Test", symbol: "USDT", decimals: 6, - cross: [{ target: { network: "pangolin", symbol: "ahUSDT" }, isReserve: true }], + cross: [ + { + isReserve: true, + target: { network: "pangolin", symbol: "ahUSDT" }, + fee: { amount: bnToBn(125000), asset: { id: 7777, decimals: 6, symbol: "USDT", native: true } }, // 0.125 USDT + }, + ], }, ], wallets: [WalletID.TALISMAN], addressType: "substrate", - minCross: bnToBn(125000), // 0.125 USDT /** * Substrate */ endpoint: "wss://rococo-asset-hub-rpc.polkadot.io", - parachainId: 1000, + parachainId: ParachainID.ASSETHUB_ROCOCO, }; diff --git a/src/config/chains/darwinia-chain.ts b/src/config/chains/darwinia-chain.ts new file mode 100644 index 0000000..d140aee --- /dev/null +++ b/src/config/chains/darwinia-chain.ts @@ -0,0 +1,75 @@ +import { ChainConfig, ChainID, ParachainID, WalletID } from "@/types"; +import { bnToBn } from "@polkadot/util"; + +export const darwiniaChain: ChainConfig = { + /** + * Chain + */ + id: ChainID.DARWINIA, + network: "darwinia", + name: "Darwinia", + nativeCurrency: { + name: "RING", + symbol: "RING", + decimals: 18, + }, + rpcUrls: { + default: { + http: ["https://rpc.darwinia.network"], + webSocket: ["wss://rpc.darwinia.network"], + }, + public: { + http: ["https://rpc.darwinia.network"], + webSocket: ["wss://rpc.darwinia.network"], + }, + }, + blockExplorers: { + default: { + name: "Subscan", + url: "https://darwinia.subscan.io", + }, + }, + + /** + * Custom + */ + logo: "darwinia.png", + assets: [ + { + icon: "usdt.svg", + id: 1027, + name: "Tether USD", + symbol: "ahUSDT", + decimals: 6, + cross: [ + { + isReserve: false, + target: { network: "assethub-polkadot", symbol: "USDT" }, + fee: { amount: bnToBn(700000), asset: { id: 1984, decimals: 6, symbol: "ahUSDT", native: true } }, // 0.7 USDT + }, + ], + }, + { + icon: "pink.jpg", + id: 1028, + name: "PINK", + symbol: "ahPINK", + decimals: 10, + cross: [ + { + isReserve: false, + target: { network: "assethub-polkadot", symbol: "PINK" }, + fee: { amount: bnToBn(700000), asset: { id: 1984, decimals: 6, symbol: "ahUSDT", native: false } }, // 0.7 USDT + }, + ], + }, + ], + wallets: [WalletID.RAINBOW, WalletID.TALISMAN], + addressType: "evm", + + /** + * Substrate + */ + endpoint: "wss://rpc.darwinia.network", + parachainId: ParachainID.DARWINIA, +}; diff --git a/src/config/chains/index.ts b/src/config/chains/index.ts index e154efc..fa4b4d7 100644 --- a/src/config/chains/index.ts +++ b/src/config/chains/index.ts @@ -1,2 +1,4 @@ export * from "./pangolin-chain"; +export * from "./darwinia-chain"; export * from "./assethub-rococo-chain"; +export * from "./assethub-polkadot-chain"; diff --git a/src/config/chains/pangolin-chain.ts b/src/config/chains/pangolin-chain.ts index 4c67104..e010311 100644 --- a/src/config/chains/pangolin-chain.ts +++ b/src/config/chains/pangolin-chain.ts @@ -1,4 +1,4 @@ -import { ChainConfig, ChainID, WalletID } from "@/types"; +import { ChainConfig, ChainID, ParachainID, WalletID } from "@/types"; import { bnToBn } from "@polkadot/util"; export const pangolinChain: ChainConfig = { @@ -44,20 +44,20 @@ export const pangolinChain: ChainConfig = { decimals: 6, cross: [ { - target: { network: "assethub-rococo", symbol: "USDT" }, isReserve: false, + target: { network: "assethub-rococo", symbol: "USDT" }, + fee: { amount: bnToBn(3600000), asset: { id: 7777, decimals: 6, symbol: "ahUSDT", native: true } }, // 3.6 USDT }, ], }, ], wallets: [WalletID.RAINBOW, WalletID.TALISMAN], addressType: "evm", - minCross: bnToBn(3600000), // 3.6 USDT hasAssetLimit: true, /** * Substrate */ endpoint: "wss://pangolin-rpc.darwinia.network", - parachainId: 2105, + parachainId: ParachainID.PANGOLIN, }; diff --git a/src/hooks/use-balance.ts b/src/hooks/use-balance.ts index 6e87a82..d980a3d 100644 --- a/src/hooks/use-balance.ts +++ b/src/hooks/use-balance.ts @@ -7,19 +7,21 @@ import { forkJoin, EMPTY } from "rxjs"; export function useBalance( bridge: EvmBridge | undefined, value: { address: string; valid: boolean } | undefined, - position: "source" | "target", + type: "source" | "target" | "usdt", ) { const [balance, setBalance] = useState<{ asset: { value: BN; asset: Asset } }>(); const updateBalance = useCallback(() => { if (bridge && value?.address && value.valid) { return forkJoin([ - position === "source" + type === "usdt" + ? bridge.getSourceUsdtBalance(value.address) + : type === "source" ? bridge.getSourceAssetBalance(value.address) : bridge.getTargetAssetBalance(value.address), ]).subscribe({ next: ([asset]) => { - setBalance({ asset }); + setBalance(asset ? { asset } : undefined); }, error: (err) => { console.error(err); @@ -31,7 +33,7 @@ export function useBalance( } return EMPTY.subscribe(); - }, [bridge, value, position]); + }, [bridge, value, type]); useEffect(() => { const sub$$ = updateBalance(); diff --git a/src/libs/bridge/base.ts b/src/libs/bridge/base.ts index 9d0f78b..7aaf2d1 100644 --- a/src/libs/bridge/base.ts +++ b/src/libs/bridge/base.ts @@ -96,6 +96,14 @@ export abstract class BaseBridge { return { value, asset }; } + async getSourceUsdtBalance(address: string) { + const asset = this.sourceChain.assets.find(({ symbol }) => symbol.toLowerCase().includes("usdt")); + if (asset) { + const value = await this.getAssetBalance(this.sourceApi, asset, address); + return { value, asset }; + } + } + /** * Supply */ diff --git a/src/libs/bridge/evm.ts b/src/libs/bridge/evm.ts index 1b3a9d9..f7f869b 100644 --- a/src/libs/bridge/evm.ts +++ b/src/libs/bridge/evm.ts @@ -32,8 +32,8 @@ export class EvmBridge extends SubstrateBridge { return; } - async transferAssetWithPrecompile(sender: string, recipient: string, amount: BN) { - const extrinsic = await this.transferAsset(recipient, amount); + async transferAssetsWithPrecompile(sender: string, recipient: string, amount: BN) { + const extrinsic = await this.transferAssets(recipient, amount); const account = sender as Address; // const estimateGas = await this.publicClient.estimateGas({ diff --git a/src/libs/bridge/substrate.ts b/src/libs/bridge/substrate.ts index d0b93d7..90535ee 100644 --- a/src/libs/bridge/substrate.ts +++ b/src/libs/bridge/substrate.ts @@ -1,5 +1,5 @@ import { BaseBridge } from "./base"; -import { BN, BN_ZERO, bnToBn, u8aToHex } from "@polkadot/util"; +import { BN, bnToBn, u8aToHex } from "@polkadot/util"; import { Asset, ChainConfig } from "@/types"; import { ApiPromise } from "@polkadot/api"; import { decodeAddress } from "@polkadot/util-crypto"; @@ -25,20 +25,19 @@ export class SubstrateBridge extends BaseBridge { } /** - * From Pangolin to Asset-Hub + * To Asset-Hub * @param recipient Address * @param amount Transfer amount * @returns Promise> */ - async transferAsset(recipient: string, amount: BN) { + async transferAssets(recipient: string, amount: BN) { const section = "xTokens"; - const method = "transferMultiasset"; + const method = "transferMultiassets"; const fn = this.sourceApi.tx[section][method]; const Parachain = bnToBn(this.targetChain.parachainId); - - const _asset = { - V3: { + const assetItems = [ + { id: { Concrete: { parents: 1, @@ -49,7 +48,23 @@ export class SubstrateBridge extends BaseBridge { }, fun: { Fungible: amount }, }, - }; + ]; + if (this.cross && !this.cross.fee.asset.native) { + assetItems.push({ + id: { + Concrete: { + parents: 1, + interior: { + X3: [{ Parachain }, { PalletInstance: 50 }, { GeneralIndex: bnToBn(this.cross.fee.asset.id) }], + }, + }, + }, + fun: { Fungible: this.cross.fee.amount }, + }); + } + + const _assets = { V3: assetItems }; + const _feeAssetItem = bnToBn(assetItems.length - 1); const _dest = { V3: { parents: 1, @@ -60,39 +75,49 @@ export class SubstrateBridge extends BaseBridge { }; const _destWeightLimit = { Unlimited: null }; - const extrinsic = fn(_asset, _dest, _destWeightLimit); + const extrinsic = fn(_assets, _feeAssetItem, _dest, _destWeightLimit); return extrinsic; } /** - * From Asset-Hub to Pangolin + * From Asset-Hub * @param recipient Address * @param amount Transfer amount * @returns Promise> */ - async limitedReserveTransferAsset(recipient: string, amount: BN) { + async limitedReserveTransferAssets(recipient: string, amount: BN) { const section = "polkadotXcm"; const method = "limitedReserveTransferAssets"; const fn = this.sourceApi.tx[section][method]; const Parachain = bnToBn(this.targetChain.parachainId); + const assetItems = [ + { + id: { + Concrete: { + parents: 0, + interior: { X2: [{ PalletInstance: 50 }, { GeneralIndex: bnToBn(this.sourceAsset.id) }] }, + }, + }, + fun: { Fungible: amount }, + }, + ]; + if (this.cross && !this.cross.fee.asset.native) { + assetItems.push({ + id: { + Concrete: { + parents: 0, + interior: { X2: [{ PalletInstance: 50 }, { GeneralIndex: bnToBn(this.cross.fee.asset.id) }] }, + }, + }, + fun: { Fungible: this.cross.fee.amount }, + }); + } const _dest = { V3: { parents: 1, interior: { X1: { Parachain } } } }; const _beneficiary = { V3: { parents: 0, interior: { X1: { AccountKey20: { network: null, key: recipient } } } } }; - const _assets = { - V3: [ - { - id: { - Concrete: { - parents: 0, - interior: { X2: [{ PalletInstance: 50 }, { GeneralIndex: bnToBn(this.sourceAsset.id) }] }, - }, - }, - fun: { Fungible: amount }, - }, - ], - }; - const _feeAssetItem = BN_ZERO; + const _assets = { V3: assetItems }; + const _feeAssetItem = bnToBn(assetItems.length - 1); const _weightLimit = { Unlimited: null }; const extrinsic = fn(_dest, _beneficiary, _assets, _feeAssetItem, _weightLimit); diff --git a/src/providers/rainbow-provider.tsx b/src/providers/rainbow-provider.tsx index baa4beb..641d0c1 100644 --- a/src/providers/rainbow-provider.tsx +++ b/src/providers/rainbow-provider.tsx @@ -6,13 +6,13 @@ import { darkTheme, getDefaultWallets, RainbowKitProvider } from "@rainbow-me/ra import { configureChains, createConfig, WagmiConfig } from "wagmi"; import { publicProvider } from "wagmi/providers/public"; import { PropsWithChildren } from "react"; -import { pangolinChain } from "@/config/chains"; +import { darwiniaChain } from "@/config/chains"; import { APP_NAME } from "@/config"; const projectId = process.env.NEXT_PUBLIC_WALLET_CONNECT_ID || ""; const appName = APP_NAME; -const { chains, publicClient } = configureChains([pangolinChain], [publicProvider()]); +const { chains, publicClient } = configureChains([darwiniaChain], [publicProvider()]); const { connectors } = getDefaultWallets({ appName, projectId, chains }); diff --git a/src/providers/transfer-provider.tsx b/src/providers/transfer-provider.tsx index 72fc060..0089fba 100644 --- a/src/providers/transfer-provider.tsx +++ b/src/providers/transfer-provider.tsx @@ -16,6 +16,7 @@ interface TransferCtx { assetLimit: BN | undefined; targetAssetDetails: PalletAssetsAssetDetails | undefined; bridgeInstance: EvmBridge | undefined; + usdtBalance: { asset: { value: BN; asset: Asset } } | undefined; sourceBalance: { asset: { value: BN; asset: Asset } } | undefined; targetBalance: { asset: { value: BN; asset: Asset } } | undefined; transferAmount: { valid: boolean; input: string; amount: BN }; @@ -66,6 +67,7 @@ const defaultValue: TransferCtx = { assetLimit: undefined, targetAssetDetails: undefined, bridgeInstance: undefined, + usdtBalance: undefined, sourceBalance: undefined, targetBalance: undefined, transferAmount: { valid: true, input: "", amount: BN_ZERO }, @@ -142,6 +144,7 @@ export default function TransferProvider({ children }: PropsWithChildren { try { - const receipt = await _bridge.transferAssetWithPrecompile(_sender, _recipient, _amount); + const receipt = await _bridge.transferAssetsWithPrecompile(_sender, _recipient, _amount); notifyTransaction(receipt, _bridge.getSourceChain()); if (receipt?.status === "success") { options.successCb(); @@ -176,8 +179,8 @@ export default function TransferProvider({ children }: PropsWithChildren