From f9cf7a9c08149c47ce59ad05aea00f4d173128ca Mon Sep 17 00:00:00 2001 From: David Cumps Date: Wed, 23 Oct 2024 01:18:51 +0200 Subject: [PATCH 001/127] feat: add chainflip swagger schema --- packages/unchained-client/openapitools.json | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/packages/unchained-client/openapitools.json b/packages/unchained-client/openapitools.json index a8062c8f840..ad218416a77 100644 --- a/packages/unchained-client/openapitools.json +++ b/packages/unchained-client/openapitools.json @@ -225,6 +225,19 @@ "supportsES6": "true", "useSingleRequestParameter": true } + }, + "chainflip": { + "inputSpec": "https://chainflip-broker.io/docs/v1/docs.json", + "generatorName": "typescript-fetch", + "output": "#{cwd}/src/generated/chainflip", + "enablePostProcessFile": true, + "reservedWordsMappings": { + "in": "in" + }, + "additionalProperties": { + "supportsES6": "true", + "useSingleRequestParameter": true + } } } } From b0fef838121bc70eaf53d22eb8d5b2ad2cdcf113 Mon Sep 17 00:00:00 2001 From: David Cumps Date: Wed, 23 Oct 2024 03:06:20 +0200 Subject: [PATCH 002/127] feat: add chainflip icon --- .../components/SwapperIcon/chainflip-icon.png | Bin 0 -> 12385 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/components/MultiHopTrade/components/TradeInput/components/SwapperIcon/chainflip-icon.png diff --git a/src/components/MultiHopTrade/components/TradeInput/components/SwapperIcon/chainflip-icon.png b/src/components/MultiHopTrade/components/TradeInput/components/SwapperIcon/chainflip-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..fb5892136e9dcae379de9dcf880ed8b4fc57f798 GIT binary patch literal 12385 zcmZ{KMN}M2)Aiu)?n7{QcXziS0fG(gPJqEBIKkcB2^!qpU4uKpVX*Icm;d7LI^Fkl zRo|*Uy{Jv!D0NjiG-P6A004ldATO=?A2$DQBEtW-icG|17_& zEcrhVg1dr>48kEi3O*)tW6hm70Kf*VAT6Qoy?*KM(?%nca(pd))OFoe32j?YZH6bi z=-HRsH~bB2+?7OPOrHNha6#7BXS``{yPrX1F&2=D7|}eG`7l*IFBRF7L@yA zUS_s+3MjY>S+c!*gU1wu8C26bUnrtq&Vsr?G0lwXV@{|-2sMM2zbWsuWVVJrVYNP| zn1&|gC=??{Eujd?6b%A{sFt%7T*$y?w1kwXaM6ltC>aP($_n@Gze0p&wOT4NSW?|BfS$a1vHse^-`Q zHP_uFS2;DMCw}^g+#do}Y3MJBBQ79LB#?i%O;g~RE({B9SC^tbLi0#!fhIB=Yvoh{ zY(>Yt9txzdFjjtR@^=1Hd$S^3q$WF<1yC-a2H)|0ceg^Y&ZV|;4YFT=NkJ@0ESr%R z*{Vy+qeUU-@^59M-iSfUXL0D-M+G0PR6EW$wJ>Ezm%s4S$JHD-fKF28hXjxYv1ZA` zwhiYi=~eyofpH;|UvewnNwDad#Sbc!w&GX|>|hEJg!5aCo@^$kmgO()g=3bf>y+#u zI=~AIpdJ(CA0~>YoYx6+EWegv_2)XfY=liJkv>4_kY*KoFT66aZl) zumN`ZD^JTqKc)rpS67o5HU*EN3VZq*e!ZgFr}~pzkUv(8)7*WvFBW$W-0qk-#^o`2 z;5%>tRpecEGhB3m|IXUvB%Lh~>UYsm!gOT@B>bMnXyF>vA0nrj;iAq0c^UR&thx?x zfnOM3F37vRsml+TL@(a3UAQSd;1N7}f?4HnM1Cl?dx|3RWf`8+_hT+kdu5o!WFnp& zTO>aD=J%+Bp=cZwDK?tP>y9hW6}P|4&ki$7h4`w625QlsjfT5VJr_lr-6FA;%~Qnc zNz7P=24syT;onGQNOT3q)EEzZ9dU6l&&NYLVOhyTW9OY!hOkP%Sy>s7aVPmF;aHP8 zQ+aS6ZVYgeQn~Jm?!~SCAcX3{eEqgYbO{|+Ig0Z8 zq`VrPy-!5-cRY*Kz2r9zoI29ht!0NY^S@m2@LxpJgPww&Il(;se&SVteAV=VSdjsiTY0vpD@d&4@R;H)!l_BaGB6(bL-p<8M{M_T%~T_PXy zLQ&a7m#T+wDQJUw^ver0jh@_Pp2rFbJ=px#Z6A1VsQAC75FoaP@T4xl3h^;bF6{oh z9nViw0xp+=-Qdb%uBHik)%&mXQ}I?L>>l}koiGaAN0X$ zgZI#Jd!-P5Y!7JgXjDAAZ$%7qa>G>Ut*yO}WA90_JBba)oz>OD!eqREcu>}iSOh<) zE$~&QMmq~?hS;DYmn-zn{N`@vz4=dFYE5XsMhR%&W9E%4;9v26ZoL=9I|n!q5q24p z;f4gb6?gbBIPDt}*j3abp}r22&$R2t<+TZ~_`1C>V$v{S5sgAyFY!n}&6MWm^Wc=i zi%QiPw$)cd`_+JGr+~Zk&;}>(-~Np0nQ=)H6^YuWP;8Sx2^B}J0|!+YDH5uBj_}^l zxE~>FZ;9hfA#*!*HRBY~EzG2rCEqXY(1!a`c9}nKrQPve2c#GJ#okxtLm;it1^yB_ ze2Ek5tvTa^@9a+U(D#xBzeC|ChY2k)HcR{nugr{+;h&66ToGb7-|BRs2hFtS=;tjn z&=W`4gG3$DN>{7gWc;hfEAuT&q$r;5)Iy$QHSX)fjxO5 z9`qD6#oT!lkiOMDZ$wLWIFHsRd89st@&0BgK?2*k#G4CwUm=e<7evKYdQJ%PKS-PM zrgD}xK1I1X#Hsk}?7sV69$FSlQFy)U=fg|v;EdduOpD}2s_sjRP^Y&i%T#w4r{-L2 z!ptb`5xEEW91VK5c&jf73NWdx!O4lqB97SYE8NaE>^%0;Q=Z$t_N^RObbM%5A}olk zRA_`%o;h4%TkecC0-80EjrKE6W)G-OPP!)f>x)P>+J`2QZGp@=h9x-tF&cPaa%ffg zZ}s8?a1r?V5S#9-dWr*fhx~0)GyJvOXulj$nw8Q72jC4h^*&+3hL<|wq&ddPeyteF zq%WS#*%A=K&b@3IdpgVBpedcrv?k#!WK687WEt*xz!g$Ww+ju(DLp)OrT(|ULX>|n zbt8+ORrcz2bnj26U1F6o4&)0ol_s+jcj|i30+iVKv^+9mZe#otEbGfrCWPhlrqs)9 z^ltcYEQs4ixIUa1K;B28hZ$)5K-}Vzs*govmy+q!@L*+RGFQy*mhiT4l}$yDm3cmF z#sXf__juStbv>wopo>>-&ED`aRpHDX%2I20YoQo!XB8ljrw*!(UoUE1s_Oo&28QQXaH__Wps3SrpQPb)lu= zgGNFgMSEe2bs-m)HeW~o;FIEsYULFV@{SN&CWL-KmgVkJDkbQr3uL@&4;O9)bzH=+a!i6kq(Y5f{kNM5aAv!Vc~w zdn0e-bNqf(&~4}9&oDwQgMe+5n3d6gOdwH*A~~8Vx#t_`=s4Q!5f>Qyw0B$S0i7ZK z`wt2gGwU(LrEKmmbF>sSwzppanKzcgR>#aIyn;q`iefSHJ&596CCHfbWlC(r6FVM5 z(7-1e(}ccBL`n~bG3y}Tl*M19YqypW;hVeie|?1P4eIYYn-qd`3G22Bx;e52<(~{I zrf^NAag{O8Q2rL|$#O$7`kev~nt-`OR38)~sG))VW^ZQ2+FqcMK@)){knyi zDa%E^KPr&U(Rp)-hI^n}aVSq<LbVvh`?e?OL6qc#h$pLY;tDQ>=CNLE9=%YdYc zB&u(M`X=EAK|I`kN zXm(X{4pw~Gq6;U$4BuPTZw5T2TS6Ut*k@=?K^NN&-ckK?wSRfYXghA;;NAK0o}95n z=OZe*4&5eGCYZ}}Cpk)T3w6vzOWRW_$0d|S3jdnr>#c4u~G)k78c)T- zZL0j{k&$kzq8eUJy`_46m}++;3w^j*5w?$w>cJtna~lqEthcm6QABeyC3! zgbj^z!!e3sz92cSZ^9D}qyjI1>yAGRz?*ig9e!MKu|vCK;2OT#(D@>g>4O4h+)0;q z&(Hx`>ocAi>vfd)dYi^56x1AP#sP=?r~?HwqY@wGsJPMF)Q8t1^Bt)Uc%2io!8F#) zJz;~4f70SCy$5BCdB|6y!m8Ip%hqGR*W(1V9RR=Bv9<8CXYJThz7T_QSRzc4G{A-| zIYm0Cp&}&{J7yoPIOS~Q@H}8Wzl9Fb1_7}w?8s*lq)Cd$oq(?ytH_9lhb^YWbb&x* zweM6mJg;SON#S{Gg-seaXIws$YjCL6X4>08YFI0Zae6st+f{VK_#6H@h}ZP7v-a@3 zoR&%BuGMU%zX9Qqv7|i=hQGOXsw2aocr9UpT;?6CI{Uu@rkS!LK4f(FV&bct`XgRQp$SWdjUC`r92jb+ z+iLEYWkFRbKMJR+<^c9kEywuDzZ{|0aJCtA>Ty$y2~J@(X|nxaQQ`FQZD4-=m+yrX zU<~(<0gwkxJWsp7DdT%;3A-4dlxv(Qn}qbn$w*6RP$CesOWE^_Huqb*&+Fk9JVDOB98|0ei~7}gSHre zv3aK+2_(J+y_^Pd3n?N38npdFR~u84y}REwQYsH$X}h{n-#y}_Yyt?p^Pl#ArO|&*Xqnh zRc4)R;Zk>f`_=VyPtt1U-@;otn>Pfn1vbSlb+aP~X)VBB;{HA&PHnGB&j&{iZC4Cj zS&ln&zB@S)6?z(zb{!4Zf|blrl`3E$N4;NH$LaX-Vz&U_(9c5=O>gIXQm5#?X1u}p zh#i>67?fGB=;PV4*fhnQ+A&ldsf8DRpWiWBE@LPd8*Mk?2UL|&dgZuWN-X@)5+PX8 z_B5EdI%(DNK>&JP0`iaJ0prlquDj;ndf5k8K-{gbx9@qQvWGXG>nwtdH6~=T~`#cX2=rfQ*jXEhGsOl*^)W9D- zazCKkO4}(Sw~n$Wj^kVs4ki8NZ}_gi7M_t4$xfYAfSx|qPLl8JOHtv{0>R9Cu3 zfkD!bCf_UxW9y7lMKg?y zdgjVR0M`(gF9jh7%*!-vDvuWyIoWb3LOD&@e1-=cu2hNdp@A$PuANG8p$ z|51G%Cwmu#q83zmMuG%1y7~ z>Ob{XXp5o9pdphp0r=h`e_M)fD33U~e#=m)3YW@nE1sEu9k7|jO z(udy^;`;In&2T(0tlCOSH0I^}LuE%|4}^$N4_S)Z+zVhuZo5qeEv`ukNx$qwCeG+& zv;8Y6+|C3?Zop)k-0@5Xs#5x7`i^F9{WycB!-%7H8+Z<+vOdt%R{aN9PAP-dG~Ck- z!qkAZLc84z$XFQ|HO0jk9Xq)aKRREwHqG#NF)tsq>Gs{ERX=yYdRtmYwoCvK-Exbm z4)~?MF~yVdY=daqDwD?8rZ=E{kJ0WTm;WtpqCX@R2bD2l+T!Zh;~!%4r>!t>M;f(e z%~hc>XaYdpmX}azZcpS|4W5nc@2(=7cfJ-$LTu({I4!hySAL zd3q;HKqLzuGN(?;rc{RZ}Ih_Wwiii(0?H^}l24okRiN)(fE2^+ zc%#f0pI-PS9d%J{H(R5up*RhAusHlKwEY#UM#dtGFo`FUeRp)$+N!vb5r{vAifHUR zWAL{)%QLzKQdzDDD{gk1P3YOCnP=g`OS|6RVaG*@`R{LM-X$oca0%~4c8?`j&T_c?^T1H*M!|r3~D^YWA!z`7t zI`HywHqjH?_BLPbo|cn~x|=9uJuD|!{kIK<{j0lPtBN~FHVQJ78qrv~`@C2(f5in^!U| z>B9FvOdZi9J}zz$im)iu43=y-`5HJ!A@L$nC$FA{cdmt&3qM4ifRbGbH9P+9V-4sV`QM?j5j+^<+F4h2Qp*s9c_Y$x-M)bPTrCMFWaDZ4B)Wp7Ff}P|A%8-a<#4(j6*>mi0O|lX4yh`zk=bg()r`4s>`#**S^yRxz{i~DOg z@$=3_M)ylIE1AvXA=3%rl2a#_JR|BX;mf=NugX~4hDRg7Z<+_v0(A)9xSpw_W zcyQH}zbBoB_jnH~gLHvex?S>N==VndrC>%>7C&;xIR(|Pt12|(p*ES!x3&a|q_eBS zAz#sTJ1CW^ETBsKz>jxuYK|F<>?R`1QNdrxzq&a85RtKZ%>zh4_YY3h)_ zW2$+V7xerTe875A@?Y~hT~$*>>?O`ISay*l!|W7vJps9!i=WIee>p1N5fq#G*@C@@ z3fEYjRC`I}*)7^FJ%6{T4iG0fYWN^}A`K2(H!omd3~EsXaZ>luNAMoH_}N$~x^pu2 zp65|H3m1H7D*fvdN}EqIs<;H?^&h^>dsghyf)|diln>Lhpo8LJ_f0o28MfYOgi7$b zT}N*OX+N9O-M&Q`HwEo~kRHL-Ps9a7Jj5-_=X>7Yg*t)&Ft&J)gD7gB*o!~V)FJd> z^dO|o)Q*J0Mpe7wI*#Fs@vS!~Sr`pXMy}w;zQHM8Z%)8mWnk@8iKFXwqw=*AfmbC_ z?oXYZhPLZ>yYr`7fBvu-CiBfi_R&zgM*cc>`0_n($s$UwiwMzt>sq~%wJ~P4_|573 zgGA(*^$+VExNEX9M2;T^V!#x&p1G%lWy<`&X+o}n?wJ-jH8X^f+=fpOJ;*>6mzzU_H=wb z7~8+j*2L2h{%FdhU{)#M?YJQ5GeRi$~25`m(oNq$LMQ3C>1wW}91rg3LpeX+6XDE}>hzzp`nb<6|pu_}5Cp zhTTdHITFs}-=K|Ky(>^n1-mpHw%eKFvb3tAmMFy@&yMfd;+<@ojCM7=}7`c_ZITu-KGVynl38($6%vLk-1 zcHdxJXG3u><*^FwIry3XE^SA4<408R#v#;OBOs;6dzu}G`xKfS1lY8CS}AUMwtZe8 zJ^Z}Dhp`by!_*`I!&Nq=1WB?_DY`h}@p2IOc>^avab5Vd+l0P^3C$lN4@6SmsW0zO?HS+!buG4xQTW2)V}xsT{J=MoWkdrI2o+0$9SZDbacv{EbIWcWq; zg^SAQzgul9#}b?2(IDjOv+Xg(NIJE*4A{&gS?i&@WZjATE_uSHO8R*{PebF6h#UU3 zmJ6cY3Kpx|z!AAcAFP}vnX_<>sYk>y7+ajHHbQv1!5%MX*O{pMsT3AU)CN-}{YOwfsr2x-kf}I#}<8XTa_WQ_x zq?)6P8Le5}J}SFhKU{^FUq_)o6&KMAIpr@KCc8EsFD0G2;>7(QhAUfBx@Z@j_tn>r z;=sHbrKpNpz3+*F3&{uy1&C~11EXXId9$YFT4mZLSDSr5kz-4(=1cHcGrUfY_Tq^N z$n)96K7Iqhga#@YEa~02b(Hfu7*b22y0jd~Jw9N>w)e;`_ruZ`*tBCCj;W<5s0SiW zoopWcNx^~-jpWiyf-P6zwZL)u%7*mPf~1z4(`nhjDGqyl_E#?csUOzaCtp<9go@0A zK=-Xrq<4H3%9Es|m%`9kARLAdC+JN}DO{|Ckc^B15(RvNV;Qu@3uz(#14Vq#M1hFFMsd&M#7Y7rukFGG!@il}?ARZnVu`6s8+#@SygM0IElS zrDHCl^A{G8_8VT@k)wZ+AvIpYabq$7|Gwe45OINtVvPE=c!Pnusei%DY<4Y{*jVaL z#vR`3ck3)dt$!~FdX_6bZgaINhU!6XMZATqht1>jq^z#O>}9x zj-R*RQ-7Jj)tonw#j*f9&V)HmPm0?LQ$%$+Y7^&B1N+|>7PLUJd^H`N?GHz1EuKqU zI)I#VSaTH=uj|q9i&GnEt_2zf1?g$^I=A{WD;)6xE5ay;7#XHhhS%Iq9f{d>TD}=B zDkuh>a(-HtXnUXHU*Y{26rR^_@oInU_;R~XMN%w5;76)O+TL&a7QHaIf*hfJbnX^( zQwfP3HMa+v8*?RYI?&`_6GKt}2yLT81K!4?gf;mai!qSZ_PTDXD=}8V4oj^t3SUX4 zjOt0nrbGE*ipflgBfFaR%)fS&x@@TgZ#0^+VY9)SK5d3C?#sT)$Y>sK$wIox}%?WYo4$`xV<0H(suQ0paF08FK{_(`Cq?f5)pT> zle={hn)actMShRFL$>&AoN?GGFI_5ITu3mh_ZnPRxy;4%)d&i9BsEhnI?hQ$_i zhv%k>5-{mf@hqL)p0~CzttNb#q?XtHGn!l)H+aa+g4(N1a0Yh_BzUUgUoWv*ETg!Y z_Ym9g+^`>+A|cDaB=^u(%~Stm;G1?|C@0On{@Dl4n3^cdohpsWKJvi}%2Ln`U)$1g z>&6Pu#bcUV@=u)(wL z?F=1&U)mDTv5=^9rli><2I+vS{xze9voX!M)uy+ zAt~Vb$pS4Dr$V}w>+2}n-wTf-dkNRuUZ=GOJGl?xG{4zdTfTE5&y)-KOTtk8q-X&= zjH$-S!%THrfrzF|lKbvrdI83&RascT9>-j`8n2KOX6qj}+f0te&r2i&L2^0jSBGC^ z#nG1*F8=yP4Mz4l)K z7s}Do3xDwZh-PsB?b7f;`a&8$`m&8p@yOz^zqK^(88B60X1UUXln-|k6+y2u)EVL1 zgfagTAj3mm;QG;-k8xKbKX|zvDB|d%pBUM%Y^}>j1nhe^>4dhds;wrS-7b$M2s~mQ zqt%(6kBd(a6&IkuLs9NRG#H0HdaKW2xM8U~WRKZ+WrpgL6c1_d&ko}=vNvXugutmi zI#0+~W39VlcwBOGR&v-V5M z!9lKsZ4rGG3)M5w>?WQ0J*M!SY!S$34N4B9u0By7 z1pzNr@bk=k{5CX7TirLUoZQ^(7UHQ7)lW3G9NNpki(oqZlm<6BXgSU}(-}rS^ z1OwS^!;8I{gJTU&-3H1x_)i;!^F5!m3=G-iWqNF&<#*C)@9`bWCkh42&I&--6ex9OT_P&be>oOr}li~0%C*K`Tc~sB9 z4kmdUB9U0O&e!1uE+vlTPnY^e&ui{1%UWq@7?a|4;DBCYQ^ad$NH3IQBw-9w+kanY z#?B)=H)6ubTwY{i^$|K6M-h%|4Bn9WEkT4xFk**8C%?#6M9=t| z2%P#tTz2Iv3&qO~9c5R6XHDAT9{=eGsVw~k@;Lpkw{0FiLb|&j zF`RmKSNPw3w%D@H=!Sr~XErVu^fs7K5-=`lXgX~4;f&|JLY^mtw^7En^Fej1mph08e%sw{!Cs7k> zGFWIA9Ew;na}e@BUMi~1kP6B9N)#Zi_jwfv1hm>_Mca0m*a@nYJrgq6s}UDDif2In zd-Ibhr$HUIkjx8bn5;bS7oRUZ{nd3a}vsAbWA@O+5!m9lrTZ=AmLG6Av z8!~IF=qeQRDi1P%&cdIn#2$7`45%j(Z8y4mq5bsMUq$_Jz!lE{Tg6`LTpwwO>17mu z%oasvllHoUz05)%Dz>Dutt-F4&qg{fGrYg=nL%n!-!su5j-P4D4_T?DQW#W)b|o60 z?rTuX8jB1%J^Mo^TX#J>$Nd=t$M@TYvftXLt=Wa1^;Bq4_w@IrSqMntNt~;?!vR2z zl{>Th+O0IFZi^+2CpY&YCAn|=aST`A)@w)g>v=DY;pbZ{MVPKlsn6hzW40TdFT*KR z$oOX-s!W8>blqigsz{l9pd9dGLs&OlMEqD_CQ)wKJXIGe_^ORPmI~yq52bo~{`8_+ z%z4&caYv3exfH7Z%A5bYLmyHlso@(E-9|;d8CkoEHRNRSRHOIyWvdyaA52v5=Nh9z zZ}wTvDD9#By{baCF1B9PKmQQwL_=vl?kw`A+WgRqbnf8ShYsJ;4vmmq ztFnn`w$55e=?(NfY@1S<;{|Ddu(9@M_OuLzHVUN0IxnRu{&5#dWRx(Zd#Pc-w=U*C zbx`Q^zLmRy!#CfRy%yrqkspGcB*f0mTZG{LiW$OXm$r$aqlC&PYmSevxHs?jQ#X0z zSE;`7Ep{oQ$i&N{Qxg@&8JW$!Di1yX9pMJQo(BKDO5oQKgY_N0iw*>AUyd8>eUY#gndwQv4S8^$5cL5?T$w=m< z<`}ZAR;s7t&9yrwufzU&q~1HM+buT^RJOa$6<*?ObX4|>d37YR{)og3{wV~7@nu41 zJ#aab8?vhx-xqGORg+$s2qxDv`|$|*#zx+}^|xX!i-1yi6z905?nGwh_T z5Ox}1cZ6QE&CU((a&!Tk9A@e{cYC7;#Kz8&=M=+fA$Ing(#~GER`8+}6oWf%gTp=Wv&32t-kb z$A-NH>KTcz(CxvWOK&USKm{dY^9P|VLEWTxj4?fVoyu5RkOqG>q-4>w^nAXfo6&YY z?37}~SoODi!Q)*TKrf~|J{1aWmEQihv@L86nOsr5vS0qGB6rcx2Euoe%YL-#gyn#T zLX8zWef7`1f)NDF{fhI5C@5+`W_ry|G1Ys>+Iy1H(^`>Zf9|Q6R&mx%NubD?AS;u> zw(Q@wr81oPU%?zGL!A<<;i0SxC^sqGdar2QEi;o3v-Y3R17;YZq2 z5>!y%*%&UqA8nC-PqXp}%-+S{D)yU;yjt7vs?<$f#4lk#5) OfP##wbgiUm@c#iojLL}s literal 0 HcmV?d00001 From 6f4b2cd78098495fb7f2284d0f4a6fd00e555237 Mon Sep 17 00:00:00 2001 From: David Cumps Date: Wed, 23 Oct 2024 03:07:32 +0200 Subject: [PATCH 003/127] feat: add chainflip env settings --- .env.base | 3 +++ src/config.ts | 5 +++++ src/state/slices/preferencesSlice/preferencesSlice.ts | 8 +++++++- src/test/mocks/store.ts | 3 +++ 4 files changed, 18 insertions(+), 1 deletion(-) diff --git a/.env.base b/.env.base index 0105b0ac86c..244bc34f633 100644 --- a/.env.base +++ b/.env.base @@ -58,6 +58,9 @@ REACT_APP_FEATURE_DYNAMIC_LP_ASSETS=false REACT_APP_FEATURE_READ_ONLY_ASSETS=true # swapper feature flags - other .env files will override these +REACT_APP_FEATURE_CHAINFLIP=true +REACT_APP_FEATURE_CHAINFLIP_BOOST_SWAPS=true +REACT_APP_FEATURE_CHAINFLIP_DCA_SWAPS=true REACT_APP_FEATURE_COWSWAP=true REACT_APP_FEATURE_LIFI_SWAP=true REACT_APP_FEATURE_ONE_INCH=false diff --git a/src/config.ts b/src/config.ts index 969b8871551..d65e598158f 100644 --- a/src/config.ts +++ b/src/config.ts @@ -177,6 +177,11 @@ const validators = { REACT_APP_FEATURE_FOX_PAGE_GOVERNANCE: bool({ default: false }), REACT_APP_FEATURE_LIMIT_ORDERS: bool({ default: false }), REACT_APP_ZRX_BASE_URL: url(), + REACT_APP_FEATURE_CHAINFLIP: bool({ default: false }), + REACT_APP_FEATURE_CHAINFLIP_BOOST_SWAPS: bool({ default: false }), + REACT_APP_FEATURE_CHAINFLIP_DCA_SWAPS: bool({ default: false }), + REACT_APP_CHAINFLIP_API_KEY: str({ default: '6ba154d4-e219-472a-9674-5fa5b1300ccf' }), + REACT_APP_CHAINFLIP_API_URL: url({ default: 'https://chainflip-broker.io' }), } function reporter({ errors }: envalid.ReporterOptions) { diff --git a/src/state/slices/preferencesSlice/preferencesSlice.ts b/src/state/slices/preferencesSlice/preferencesSlice.ts index b43d4362a81..3b9c3779615 100644 --- a/src/state/slices/preferencesSlice/preferencesSlice.ts +++ b/src/state/slices/preferencesSlice/preferencesSlice.ts @@ -66,7 +66,10 @@ export type FeatureFlags = { FoxPageFoxSection: boolean FoxPageFoxFarmingSection: boolean FoxPageGovernance: boolean - LimitOrders: boolean + LimitOrders: boolean, + Chainflip: boolean, + ChainflipBoostSwaps: boolean, + ChainflipDcaSwaps: boolean, } export type Flag = keyof FeatureFlags @@ -159,6 +162,9 @@ const initialState: Preferences = { FoxPageFoxFarmingSection: getConfig().REACT_APP_FEATURE_FOX_PAGE_FOX_FARMING_SECTION, FoxPageGovernance: getConfig().REACT_APP_FEATURE_FOX_PAGE_GOVERNANCE, LimitOrders: getConfig().REACT_APP_FEATURE_LIMIT_ORDERS, + Chainflip: getConfig().REACT_APP_FEATURE_CHAINFLIP, + ChainflipBoostSwaps: getConfig().REACT_APP_FEATURE_CHAINFLIP_BOOST_SWAPS, + ChainflipDcaSwaps: getConfig().REACT_APP_FEATURE_CHAINFLIP_DCA_SWAPS, }, selectedLocale: simpleLocale(), balanceThreshold: '0', diff --git a/src/test/mocks/store.ts b/src/test/mocks/store.ts index b6527734519..342a6430dd7 100644 --- a/src/test/mocks/store.ts +++ b/src/test/mocks/store.ts @@ -124,6 +124,9 @@ export const mockStore: ReduxState = { FoxPageFoxFarmingSection: false, FoxPageGovernance: false, LimitOrders: false, + Chainflip: false, + ChainflipBoostSwaps: false, + ChainflipDcaSwaps: false, }, selectedLocale: 'en', balanceThreshold: '0', From ae0d0836f6f0ce863bff1601b824c72e4f09e854 Mon Sep 17 00:00:00 2001 From: David Cumps Date: Wed, 23 Oct 2024 03:07:47 +0200 Subject: [PATCH 004/127] feat: start chainflip swapper --- packages/swapper/src/constants.ts | 13 +++++- .../ChainflipSwapper/ChainflipSwapper.ts | 25 +++++++++++ .../swappers/ChainflipSwapper/constants.ts | 13 ++++++ .../swappers/ChainflipSwapper/endpoints.ts | 44 +++++++++++++++++++ .../getChainflipTradeQuote/getTradeQuote.ts | 26 +++++++++++ .../src/swappers/ChainflipSwapper/types.ts | 11 +++++ packages/swapper/src/types.ts | 5 ++- .../components/SwapperIcon/SwapperIcon.tsx | 23 +++++----- .../useGetTradeQuotes/useGetTradeQuotes.tsx | 5 ++- src/state/helpers.ts | 28 ++++++------ 10 files changed, 166 insertions(+), 27 deletions(-) create mode 100644 packages/swapper/src/swappers/ChainflipSwapper/ChainflipSwapper.ts create mode 100644 packages/swapper/src/swappers/ChainflipSwapper/constants.ts create mode 100644 packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts create mode 100644 packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts create mode 100644 packages/swapper/src/swappers/ChainflipSwapper/types.ts diff --git a/packages/swapper/src/constants.ts b/packages/swapper/src/constants.ts index 312b2e706b4..be95474fb03 100644 --- a/packages/swapper/src/constants.ts +++ b/packages/swapper/src/constants.ts @@ -24,6 +24,9 @@ import { thorchainSwapper } from './swappers/ThorchainSwapper/ThorchainSwapper' import { zrxApi } from './swappers/ZrxSwapper/endpoints' import { ZRX_SUPPORTED_CHAIN_IDS } from './swappers/ZrxSwapper/utils/constants' import { zrxSwapper } from './swappers/ZrxSwapper/ZrxSwapper' +import { CHAINFLIP_SUPPORTED_CHAIN_IDS } from './swappers/ChainflipSwapper/constants' +import { chainflipApi } from './swappers/ChainflipSwapper/endpoints' +import { chainflipSwapper } from './swappers/ChainflipSwapper/ChainflipSwapper' import type { SupportedChainIds, Swapper, SwapperApi } from './types' import { SwapperName } from './types' import { makeSwapErrorRight } from './utils' @@ -58,7 +61,6 @@ export const swappers: Record< ...zrxSwapper, ...zrxApi, supportedChainIds: ZRX_SUPPORTED_CHAIN_IDS, - pollingInterval: DEFAULT_GET_TRADE_QUOTE_POLLING_INTERVAL, }, [SwapperName.CowSwap]: { @@ -85,6 +87,12 @@ export const swappers: Record< supportedChainIds: PORTALS_SUPPORTED_CHAIN_IDS, pollingInterval: DEFAULT_GET_TRADE_QUOTE_POLLING_INTERVAL, }, + [SwapperName.Chainflip]: { + ...chainflipSwapper, + ...chainflipApi, + supportedChainIds: CHAINFLIP_SUPPORTED_CHAIN_IDS, + pollingInterval: DEFAULT_GET_TRADE_QUOTE_POLLING_INTERVAL, + }, [SwapperName.Test]: undefined, } @@ -95,6 +103,7 @@ const DEFAULT_PORTALS_SLIPPAGE_DECIMAL_PERCENTAGE = '0.01' // 1% const DEFAULT_LIFI_SLIPPAGE_DECIMAL_PERCENTAGE = '0.005' // .5% const DEFAULT_THOR_SLIPPAGE_DECIMAL_PERCENTAGE = '0.01' // 1% const DEFAULT_ARBITRUM_BRIDGE_SLIPPAGE_DECIMAL_PERCENTAGE = '0' // no slippage for Arbitrum Bridge, so no slippage tolerance +const DEFAULT_CHAINFLIP_SLIPPAGE_DECIMAL_PERCENTAGE = '0.02' // 2% export const getDefaultSlippageDecimalPercentageForSwapper = ( swapperName?: SwapperName, @@ -115,6 +124,8 @@ export const getDefaultSlippageDecimalPercentageForSwapper = ( return DEFAULT_THOR_SLIPPAGE_DECIMAL_PERCENTAGE case SwapperName.ArbitrumBridge: return DEFAULT_ARBITRUM_BRIDGE_SLIPPAGE_DECIMAL_PERCENTAGE + case SwapperName.Chainflip: + return DEFAULT_CHAINFLIP_SLIPPAGE_DECIMAL_PERCENTAGE default: assertUnreachable(swapperName) } diff --git a/packages/swapper/src/swappers/ChainflipSwapper/ChainflipSwapper.ts b/packages/swapper/src/swappers/ChainflipSwapper/ChainflipSwapper.ts new file mode 100644 index 00000000000..c39a13f0f03 --- /dev/null +++ b/packages/swapper/src/swappers/ChainflipSwapper/ChainflipSwapper.ts @@ -0,0 +1,25 @@ +import type { AssetId } from '@shapeshiftoss/caip' +import type { Asset } from '@shapeshiftoss/types' + +import type { BuyAssetBySellIdInput, Swapper } from '../../types' +import { CHAINFLIP_SUPPORTED_CHAIN_IDS } from './constants' + +export const chainflipSwapper: Swapper = { + filterAssetIdsBySellable: (assets: Asset[]): Promise => { + // TODO: Return only Chainflip supported coins + return Promise.resolve( + assets + .filter(asset => CHAINFLIP_SUPPORTED_CHAIN_IDS.sell.includes(asset.chainId)) + .map(asset => asset.assetId), + ) + }, + + filterBuyAssetsBySellAssetId: (input: BuyAssetBySellIdInput): Promise => { + // TODO: Return only Chainflip supported coins + return Promise.resolve( + input.assets + .filter(asset => CHAINFLIP_SUPPORTED_CHAIN_IDS.buy.includes(asset.chainId)) + .map(asset => asset.assetId), + ) + }, +} diff --git a/packages/swapper/src/swappers/ChainflipSwapper/constants.ts b/packages/swapper/src/swappers/ChainflipSwapper/constants.ts new file mode 100644 index 00000000000..3c4da0bf93d --- /dev/null +++ b/packages/swapper/src/swappers/ChainflipSwapper/constants.ts @@ -0,0 +1,13 @@ +import type { ChainId } from '@shapeshiftoss/caip' + +import {SupportedChainIds, SwapperName, SwapSource} from '../../types' +import { ChainflipSupportedChainIds } from './types' + +export const CHAINFLIP_SUPPORTED_CHAIN_IDS: SupportedChainIds = { + sell: ChainflipSupportedChainIds as unknown as ChainId[], + buy: ChainflipSupportedChainIds as unknown as ChainId[], +} + +export const CHAINFLIP_BOOST_SWAP_SOURCE: SwapSource = `${SwapperName.Chainflip} • Boost` +export const CHAINFLIP_DCA_SWAP_SOURCE: SwapSource = `${SwapperName.Chainflip} • DCA` +export const CHAINFLIP_DCA_BOOST_SWAP_SOURCE: SwapSource = `${SwapperName.Chainflip} • DCA • Boost` diff --git a/packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts b/packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts new file mode 100644 index 00000000000..94669d5dcd3 --- /dev/null +++ b/packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts @@ -0,0 +1,44 @@ +import type { Result } from '@sniptt/monads/build' + +import { TxStatus } from "@shapeshiftoss/unchained-client"; +import type { InterpolationOptions } from "node-polyglot"; + +import type { + GetTradeQuoteInput, + SwapErrorRight, + SwapperApi, + SwapperDeps, + TradeQuote, +} from '../../types' + +import { getChainflipTradeQuote } from './getChainflipTradeQuote/getTradeQuote' + +export const chainflipApi: SwapperApi = { + getTradeQuote: async ( + input: GetTradeQuoteInput, + deps: SwapperDeps, + ): Promise> => { + const { affiliateBps } = input + + return await getChainflipTradeQuote( + { + ...input, + affiliateBps, + }, + deps, + ) + }, + + // @ts-ignore + checkTradeStatus: async (input): Promise<{ + status: TxStatus + buyTxHash: string | undefined + message: string | [string, InterpolationOptions] | undefined + }> => { + return { + buyTxHash: undefined, + status: TxStatus.Unknown, + message: undefined, + } + } +} diff --git a/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts b/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts new file mode 100644 index 00000000000..871beda8e65 --- /dev/null +++ b/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts @@ -0,0 +1,26 @@ +import {GetTradeQuoteInput, SwapErrorRight, SwapperDeps, TradeQuote, TradeQuoteError} from "../../../types"; +import {Err, Result} from "@sniptt/monads"; +import {makeSwapErrorRight} from "../../../utils"; +import {buySupportedChainIds, sellSupportedChainIds} from "../../ThorchainSwapper/constants"; + +export const getChainflipTradeQuote = async ( + input: GetTradeQuoteInput, + deps: SwapperDeps, +): Promise> => { + const { sellAsset, buyAsset } = input + + if (!sellSupportedChainIds[sellAsset.chainId] || !buySupportedChainIds[buyAsset.chainId]) { + return Err( + makeSwapErrorRight({ + message: 'Unsupported chain', + code: TradeQuoteError.UnsupportedChain, + }), + ) + } + + // @ts-ignore + const brokerUrl = deps.config.REACT_APP_CHAINFLIP_API_URL + // TODO: use the generated swagger client to get a quote + + return Err(makeSwapErrorRight({ message: 'Not implemented yet' })) +} \ No newline at end of file diff --git a/packages/swapper/src/swappers/ChainflipSwapper/types.ts b/packages/swapper/src/swappers/ChainflipSwapper/types.ts new file mode 100644 index 00000000000..d48c97f7248 --- /dev/null +++ b/packages/swapper/src/swappers/ChainflipSwapper/types.ts @@ -0,0 +1,11 @@ +import { KnownChainIds } from '@shapeshiftoss/types' + +export const ChainflipSupportedChainIds = [ + KnownChainIds.EthereumMainnet, + KnownChainIds.ArbitrumMainnet, + KnownChainIds.BitcoinMainnet, + KnownChainIds.SolanaMainnet, + // TODO: Add Polkadot +] as const + +export type ChainflipSupportedChainId = (typeof ChainflipSupportedChainIds)[number] diff --git a/packages/swapper/src/types.ts b/packages/swapper/src/types.ts index 63d2a93f6e7..6feccda24dc 100644 --- a/packages/swapper/src/types.ts +++ b/packages/swapper/src/types.ts @@ -47,7 +47,9 @@ export type SwapperConfig = { REACT_APP_COWSWAP_BASE_URL: string REACT_APP_PORTALS_BASE_URL: string REACT_APP_FEATURE_ZRX_PERMIT2: boolean - REACT_APP_ZRX_BASE_URL: string + REACT_APP_ZRX_BASE_URL: string, + REACT_APP_CHAINFLIP_API_URL: string + REACT_APP_FEATURE_CHAINFLIP_STREAMING_SWAPS: boolean } export enum SwapperName { @@ -59,6 +61,7 @@ export enum SwapperName { OneInch = '1INCH', ArbitrumBridge = 'Arbitrum Bridge', Portals = 'Portals', + Chainflip = 'Chainflip', } export type SwapSource = SwapperName | `${SwapperName} • ${string}` diff --git a/src/components/MultiHopTrade/components/TradeInput/components/SwapperIcon/SwapperIcon.tsx b/src/components/MultiHopTrade/components/TradeInput/components/SwapperIcon/SwapperIcon.tsx index 9301f9536ac..06bdb15125a 100644 --- a/src/components/MultiHopTrade/components/TradeInput/components/SwapperIcon/SwapperIcon.tsx +++ b/src/components/MultiHopTrade/components/TradeInput/components/SwapperIcon/SwapperIcon.tsx @@ -4,13 +4,14 @@ import { useMemo } from 'react' import { LazyLoadAvatar } from 'components/LazyLoadAvatar' import { assertUnreachable } from 'lib/utils' -import ZrxIcon from './0x-icon.png' -import OneInchIcon from './1inch-icon.png' import ArbitrumBridgeIcon from './arbitrum-bridge-icon.png' +import ChainflipIcon from './chainflip-icon.png' import CowIcon from './cow-icon.png' import LiFiIcon from './lifi-icon.png' +import OneInchIcon from './1inch-icon.png' import PortalsIcon from './portals-icon.png' import THORChainIcon from './thorchain-icon.png' +import ZrxIcon from './0x-icon.png' export const SwapperIcon = ({ swapperName, @@ -21,20 +22,22 @@ export const SwapperIcon = ({ }) => { const icon = useMemo(() => { switch (swapperName) { - case SwapperName.LIFI: - return LiFiIcon + case SwapperName.ArbitrumBridge: + return ArbitrumBridgeIcon + case SwapperName.Chainflip: + return ChainflipIcon case SwapperName.CowSwap: return CowIcon - case SwapperName.Zrx: - return ZrxIcon - case SwapperName.Thorchain: - return THORChainIcon + case SwapperName.LIFI: + return LiFiIcon case SwapperName.OneInch: return OneInchIcon - case SwapperName.ArbitrumBridge: - return ArbitrumBridgeIcon case SwapperName.Portals: return PortalsIcon + case SwapperName.Thorchain: + return THORChainIcon + case SwapperName.Zrx: + return ZrxIcon case SwapperName.Test: return '' default: diff --git a/src/components/MultiHopTrade/hooks/useGetTradeQuotes/useGetTradeQuotes.tsx b/src/components/MultiHopTrade/hooks/useGetTradeQuotes/useGetTradeQuotes.tsx index 6bdc753ef1a..8f5f31ba69a 100644 --- a/src/components/MultiHopTrade/hooks/useGetTradeQuotes/useGetTradeQuotes.tsx +++ b/src/components/MultiHopTrade/hooks/useGetTradeQuotes/useGetTradeQuotes.tsx @@ -271,11 +271,12 @@ export const useGetTradeQuotes = () => { [shouldRefetchTradeQuotes, tradeQuoteInput], ) + useGetSwapperTradeQuote(getTradeQuoteArgs(SwapperName.ArbitrumBridge)) + useGetSwapperTradeQuote(getTradeQuoteArgs(SwapperName.Chainflip)) useGetSwapperTradeQuote(getTradeQuoteArgs(SwapperName.CowSwap)) + useGetSwapperTradeQuote(getTradeQuoteArgs(SwapperName.LIFI)) useGetSwapperTradeQuote(getTradeQuoteArgs(SwapperName.OneInch)) - useGetSwapperTradeQuote(getTradeQuoteArgs(SwapperName.ArbitrumBridge)) useGetSwapperTradeQuote(getTradeQuoteArgs(SwapperName.Portals)) - useGetSwapperTradeQuote(getTradeQuoteArgs(SwapperName.LIFI)) useGetSwapperTradeQuote(getTradeQuoteArgs(SwapperName.Thorchain)) useGetSwapperTradeQuote(getTradeQuoteArgs(SwapperName.Zrx)) diff --git a/src/state/helpers.ts b/src/state/helpers.ts index f371afa0f1f..3448e6a6d6d 100644 --- a/src/state/helpers.ts +++ b/src/state/helpers.ts @@ -5,14 +5,15 @@ import type { FeatureFlags } from './slices/preferencesSlice/preferencesSlice' export const isCrossAccountTradeSupported = (swapperName: SwapperName) => { switch (swapperName) { - case SwapperName.Thorchain: + case SwapperName.Chainflip: case SwapperName.LIFI: case SwapperName.OneInch: + case SwapperName.Thorchain: return true - case SwapperName.Zrx: - case SwapperName.CowSwap: case SwapperName.ArbitrumBridge: + case SwapperName.CowSwap: case SwapperName.Portals: + case SwapperName.Zrx: case SwapperName.Test: // Technically supported for Arbitrum Bridge, but we disable it for the sake of simplicity for now return false @@ -22,25 +23,26 @@ export const isCrossAccountTradeSupported = (swapperName: SwapperName) => { } export const getEnabledSwappers = ( - { Portals, LifiSwap, ThorSwap, ZrxSwap, OneInch, ArbitrumBridge, Cowswap }: FeatureFlags, + { ArbitrumBridge, Chainflip, Cowswap, LifiSwap, OneInch, Portals, ThorSwap, ZrxSwap }: FeatureFlags, isCrossAccountTrade: boolean, ): Record => { return { + [SwapperName.ArbitrumBridge]: + ArbitrumBridge && (!isCrossAccountTrade || isCrossAccountTradeSupported(SwapperName.ArbitrumBridge)), + [SwapperName.Chainflip]: + Chainflip && (!isCrossAccountTrade || isCrossAccountTradeSupported(SwapperName.Chainflip)), + [SwapperName.CowSwap]: + Cowswap && (!isCrossAccountTrade || isCrossAccountTradeSupported(SwapperName.CowSwap)), [SwapperName.LIFI]: LifiSwap && (!isCrossAccountTrade || isCrossAccountTradeSupported(SwapperName.LIFI)), - [SwapperName.Thorchain]: - ThorSwap && (!isCrossAccountTrade || isCrossAccountTradeSupported(SwapperName.Thorchain)), - [SwapperName.Zrx]: - ZrxSwap && (!isCrossAccountTrade || isCrossAccountTradeSupported(SwapperName.Zrx)), [SwapperName.OneInch]: OneInch && (!isCrossAccountTrade || isCrossAccountTradeSupported(SwapperName.OneInch)), - [SwapperName.CowSwap]: - Cowswap && (!isCrossAccountTrade || isCrossAccountTradeSupported(SwapperName.CowSwap)), - [SwapperName.ArbitrumBridge]: - ArbitrumBridge && - (!isCrossAccountTrade || isCrossAccountTradeSupported(SwapperName.ArbitrumBridge)), [SwapperName.Portals]: Portals && (!isCrossAccountTrade || isCrossAccountTradeSupported(SwapperName.Portals)), + [SwapperName.Thorchain]: + ThorSwap && (!isCrossAccountTrade || isCrossAccountTradeSupported(SwapperName.Thorchain)), + [SwapperName.Zrx]: + ZrxSwap && (!isCrossAccountTrade || isCrossAccountTradeSupported(SwapperName.Zrx)), [SwapperName.Test]: false, } } From 56a4003a9bafe3673369c3212fba43e800f64085 Mon Sep 17 00:00:00 2001 From: David Cumps Date: Wed, 23 Oct 2024 09:21:55 +0200 Subject: [PATCH 005/127] fix: forgot a missing type --- .../src/swappers/ChainflipSwapper/endpoints.ts | 7 +------ .../getChainflipTradeQuote/getTradeQuote.ts | 10 ++++++++-- packages/swapper/src/types.ts | 13 +++++++------ 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts b/packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts index 94669d5dcd3..480c179eda0 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts @@ -18,13 +18,8 @@ export const chainflipApi: SwapperApi = { input: GetTradeQuoteInput, deps: SwapperDeps, ): Promise> => { - const { affiliateBps } = input - return await getChainflipTradeQuote( - { - ...input, - affiliateBps, - }, + input, deps, ) }, diff --git a/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts b/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts index 871beda8e65..ee88579f345 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts @@ -21,6 +21,12 @@ export const getChainflipTradeQuote = async ( // @ts-ignore const brokerUrl = deps.config.REACT_APP_CHAINFLIP_API_URL // TODO: use the generated swagger client to get a quote - - return Err(makeSwapErrorRight({ message: 'Not implemented yet' })) + + // TODO: Temp error + return Err( + makeSwapErrorRight({ + message: 'Unsupported chain', + code: TradeQuoteError.UnsupportedChain, + }), + ) } \ No newline at end of file diff --git a/packages/swapper/src/types.ts b/packages/swapper/src/types.ts index 6feccda24dc..dcc93275946 100644 --- a/packages/swapper/src/types.ts +++ b/packages/swapper/src/types.ts @@ -49,19 +49,20 @@ export type SwapperConfig = { REACT_APP_FEATURE_ZRX_PERMIT2: boolean REACT_APP_ZRX_BASE_URL: string, REACT_APP_CHAINFLIP_API_URL: string - REACT_APP_FEATURE_CHAINFLIP_STREAMING_SWAPS: boolean + REACT_APP_FEATURE_CHAINFLIP_BOOST_SWAPS: boolean + REACT_APP_FEATURE_CHAINFLIP_DCA_SWAPS: boolean } export enum SwapperName { - Thorchain = 'THORChain', + ArbitrumBridge = 'Arbitrum Bridge', + Chainflip = 'Chainflip', CowSwap = 'CoW Swap', - Zrx = '0x', - Test = 'Test', LIFI = 'LI.FI', OneInch = '1INCH', - ArbitrumBridge = 'Arbitrum Bridge', Portals = 'Portals', - Chainflip = 'Chainflip', + Thorchain = 'THORChain', + Zrx = '0x', + Test = 'Test', } export type SwapSource = SwapperName | `${SwapperName} • ${string}` From 53cfa9fdbe6a8cc487aa3a8eb2521e01f8947c8e Mon Sep 17 00:00:00 2001 From: David Cumps Date: Wed, 23 Oct 2024 11:07:14 +0200 Subject: [PATCH 006/127] feat: build sell and buy asset strings --- packages/swapper/src/constants.ts | 88 ++++++++++--------- .../swappers/ChainflipSwapper/constants.ts | 11 ++- .../getChainflipTradeQuote/getTradeQuote.ts | 52 ++++++++--- 3 files changed, 97 insertions(+), 54 deletions(-) diff --git a/packages/swapper/src/constants.ts b/packages/swapper/src/constants.ts index be95474fb03..14d4e5ab690 100644 --- a/packages/swapper/src/constants.ts +++ b/packages/swapper/src/constants.ts @@ -3,30 +3,38 @@ import { assertUnreachable } from '@shapeshiftoss/utils' import { arbitrumBridgeSwapper } from './swappers/ArbitrumBridgeSwapper/ArbitrumBridgeSwapper' import { arbitrumBridgeApi } from './swappers/ArbitrumBridgeSwapper/endpoints' import { ARBITRUM_BRIDGE_SUPPORTED_CHAIN_IDS } from './swappers/ArbitrumBridgeSwapper/utils/constants' + +import { CHAINFLIP_SUPPORTED_CHAIN_IDS } from './swappers/ChainflipSwapper/constants' +import { chainflipApi } from './swappers/ChainflipSwapper/endpoints' +import { chainflipSwapper } from './swappers/ChainflipSwapper/ChainflipSwapper' + import { cowSwapper } from './swappers/CowSwapper/CowSwapper' import { cowApi } from './swappers/CowSwapper/endpoints' import { COW_SWAP_SUPPORTED_CHAIN_IDS } from './swappers/CowSwapper/utils/constants' + import { lifiApi } from './swappers/LifiSwapper/endpoints' import { LIFI_GET_TRADE_QUOTE_POLLING_INTERVAL, lifiSwapper, } from './swappers/LifiSwapper/LifiSwapper' import { LIFI_SUPPORTED_CHAIN_IDS } from './swappers/LifiSwapper/utils/constants' + import { oneInchApi } from './swappers/OneInchSwapper/endpoints' import { oneInchSwapper } from './swappers/OneInchSwapper/OneInchSwapper' import { ONE_INCH_SUPPORTED_CHAIN_IDS } from './swappers/OneInchSwapper/utils/constants' + import { PORTALS_SUPPORTED_CHAIN_IDS } from './swappers/PortalsSwapper/constants' import { portalsApi } from './swappers/PortalsSwapper/endpoints' import { portalsSwapper } from './swappers/PortalsSwapper/PortalsSwapper' + import { THORCHAIN_SUPPORTED_CHAIN_IDS } from './swappers/ThorchainSwapper/constants' import { thorchainApi } from './swappers/ThorchainSwapper/endpoints' import { thorchainSwapper } from './swappers/ThorchainSwapper/ThorchainSwapper' + import { zrxApi } from './swappers/ZrxSwapper/endpoints' import { ZRX_SUPPORTED_CHAIN_IDS } from './swappers/ZrxSwapper/utils/constants' import { zrxSwapper } from './swappers/ZrxSwapper/ZrxSwapper' -import { CHAINFLIP_SUPPORTED_CHAIN_IDS } from './swappers/ChainflipSwapper/constants' -import { chainflipApi } from './swappers/ChainflipSwapper/endpoints' -import { chainflipSwapper } from './swappers/ChainflipSwapper/ChainflipSwapper' + import type { SupportedChainIds, Swapper, SwapperApi } from './types' import { SwapperName } from './types' import { makeSwapErrorRight } from './utils' @@ -45,22 +53,16 @@ export const swappers: Record< | (SwapperApi & Swapper & { supportedChainIds: SupportedChainIds; pollingInterval: number }) | undefined > = { - [SwapperName.LIFI]: { - ...lifiSwapper, - ...lifiApi, - supportedChainIds: LIFI_SUPPORTED_CHAIN_IDS, - pollingInterval: LIFI_GET_TRADE_QUOTE_POLLING_INTERVAL, - }, - [SwapperName.Thorchain]: { - ...thorchainSwapper, - ...thorchainApi, - supportedChainIds: THORCHAIN_SUPPORTED_CHAIN_IDS, + [SwapperName.ArbitrumBridge]: { + ...arbitrumBridgeSwapper, + ...arbitrumBridgeApi, + supportedChainIds: ARBITRUM_BRIDGE_SUPPORTED_CHAIN_IDS, pollingInterval: DEFAULT_GET_TRADE_QUOTE_POLLING_INTERVAL, }, - [SwapperName.Zrx]: { - ...zrxSwapper, - ...zrxApi, - supportedChainIds: ZRX_SUPPORTED_CHAIN_IDS, + [SwapperName.Chainflip]: { + ...chainflipSwapper, + ...chainflipApi, + supportedChainIds: CHAINFLIP_SUPPORTED_CHAIN_IDS, pollingInterval: DEFAULT_GET_TRADE_QUOTE_POLLING_INTERVAL, }, [SwapperName.CowSwap]: { @@ -69,28 +71,34 @@ export const swappers: Record< supportedChainIds: COW_SWAP_SUPPORTED_CHAIN_IDS, pollingInterval: DEFAULT_GET_TRADE_QUOTE_POLLING_INTERVAL, }, + [SwapperName.LIFI]: { + ...lifiSwapper, + ...lifiApi, + supportedChainIds: LIFI_SUPPORTED_CHAIN_IDS, + pollingInterval: LIFI_GET_TRADE_QUOTE_POLLING_INTERVAL, + }, [SwapperName.OneInch]: { ...oneInchSwapper, ...oneInchApi, supportedChainIds: ONE_INCH_SUPPORTED_CHAIN_IDS, pollingInterval: DEFAULT_GET_TRADE_QUOTE_POLLING_INTERVAL, }, - [SwapperName.ArbitrumBridge]: { - ...arbitrumBridgeSwapper, - ...arbitrumBridgeApi, - supportedChainIds: ARBITRUM_BRIDGE_SUPPORTED_CHAIN_IDS, - pollingInterval: DEFAULT_GET_TRADE_QUOTE_POLLING_INTERVAL, - }, [SwapperName.Portals]: { ...portalsSwapper, ...portalsApi, supportedChainIds: PORTALS_SUPPORTED_CHAIN_IDS, pollingInterval: DEFAULT_GET_TRADE_QUOTE_POLLING_INTERVAL, }, - [SwapperName.Chainflip]: { - ...chainflipSwapper, - ...chainflipApi, - supportedChainIds: CHAINFLIP_SUPPORTED_CHAIN_IDS, + [SwapperName.Thorchain]: { + ...thorchainSwapper, + ...thorchainApi, + supportedChainIds: THORCHAIN_SUPPORTED_CHAIN_IDS, + pollingInterval: DEFAULT_GET_TRADE_QUOTE_POLLING_INTERVAL, + }, + [SwapperName.Zrx]: { + ...zrxSwapper, + ...zrxApi, + supportedChainIds: ZRX_SUPPORTED_CHAIN_IDS, pollingInterval: DEFAULT_GET_TRADE_QUOTE_POLLING_INTERVAL, }, [SwapperName.Test]: undefined, @@ -98,34 +106,34 @@ export const swappers: Record< // Slippage defaults. Don't export these to ensure the getDefaultSlippageDecimalPercentageForSwapper helper function is used. const DEFAULT_SLIPPAGE_DECIMAL_PERCENTAGE = '0.002' // .2% +const DEFAULT_ARBITRUM_BRIDGE_SLIPPAGE_DECIMAL_PERCENTAGE = '0' // no slippage for Arbitrum Bridge, so no slippage tolerance +const DEFAULT_CHAINFLIP_SLIPPAGE_DECIMAL_PERCENTAGE = '0.02' // 2% const DEFAULT_COWSWAP_SLIPPAGE_DECIMAL_PERCENTAGE = '0.005' // .5% -const DEFAULT_PORTALS_SLIPPAGE_DECIMAL_PERCENTAGE = '0.01' // 1% const DEFAULT_LIFI_SLIPPAGE_DECIMAL_PERCENTAGE = '0.005' // .5% +const DEFAULT_PORTALS_SLIPPAGE_DECIMAL_PERCENTAGE = '0.01' // 1% const DEFAULT_THOR_SLIPPAGE_DECIMAL_PERCENTAGE = '0.01' // 1% -const DEFAULT_ARBITRUM_BRIDGE_SLIPPAGE_DECIMAL_PERCENTAGE = '0' // no slippage for Arbitrum Bridge, so no slippage tolerance -const DEFAULT_CHAINFLIP_SLIPPAGE_DECIMAL_PERCENTAGE = '0.02' // 2% export const getDefaultSlippageDecimalPercentageForSwapper = ( swapperName?: SwapperName, ): string => { if (swapperName === undefined) return DEFAULT_SLIPPAGE_DECIMAL_PERCENTAGE switch (swapperName) { - case SwapperName.Zrx: - case SwapperName.OneInch: - case SwapperName.Test: - return DEFAULT_SLIPPAGE_DECIMAL_PERCENTAGE - case SwapperName.LIFI: - return DEFAULT_LIFI_SLIPPAGE_DECIMAL_PERCENTAGE + case SwapperName.ArbitrumBridge: + return DEFAULT_ARBITRUM_BRIDGE_SLIPPAGE_DECIMAL_PERCENTAGE + case SwapperName.Chainflip: + return DEFAULT_CHAINFLIP_SLIPPAGE_DECIMAL_PERCENTAGE case SwapperName.CowSwap: return DEFAULT_COWSWAP_SLIPPAGE_DECIMAL_PERCENTAGE + case SwapperName.LIFI: + return DEFAULT_LIFI_SLIPPAGE_DECIMAL_PERCENTAGE case SwapperName.Portals: return DEFAULT_PORTALS_SLIPPAGE_DECIMAL_PERCENTAGE case SwapperName.Thorchain: return DEFAULT_THOR_SLIPPAGE_DECIMAL_PERCENTAGE - case SwapperName.ArbitrumBridge: - return DEFAULT_ARBITRUM_BRIDGE_SLIPPAGE_DECIMAL_PERCENTAGE - case SwapperName.Chainflip: - return DEFAULT_CHAINFLIP_SLIPPAGE_DECIMAL_PERCENTAGE + case SwapperName.Zrx: + case SwapperName.OneInch: + case SwapperName.Test: + return DEFAULT_SLIPPAGE_DECIMAL_PERCENTAGE default: assertUnreachable(swapperName) } diff --git a/packages/swapper/src/swappers/ChainflipSwapper/constants.ts b/packages/swapper/src/swappers/ChainflipSwapper/constants.ts index 3c4da0bf93d..1ae1bab8453 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/constants.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/constants.ts @@ -1,6 +1,7 @@ import type { ChainId } from '@shapeshiftoss/caip' +import { KnownChainIds } from "@shapeshiftoss/types"; -import {SupportedChainIds, SwapperName, SwapSource} from '../../types' +import { SupportedChainIds, SwapperName, SwapSource } from '../../types' import { ChainflipSupportedChainIds } from './types' export const CHAINFLIP_SUPPORTED_CHAIN_IDS: SupportedChainIds = { @@ -11,3 +12,11 @@ export const CHAINFLIP_SUPPORTED_CHAIN_IDS: SupportedChainIds = { export const CHAINFLIP_BOOST_SWAP_SOURCE: SwapSource = `${SwapperName.Chainflip} • Boost` export const CHAINFLIP_DCA_SWAP_SOURCE: SwapSource = `${SwapperName.Chainflip} • DCA` export const CHAINFLIP_DCA_BOOST_SWAP_SOURCE: SwapSource = `${SwapperName.Chainflip} • DCA • Boost` + +export const chainIdToChainflipNetwork: Partial> = { + [KnownChainIds.EthereumMainnet]: 'eth', + [KnownChainIds.ArbitrumMainnet]: 'arb', + [KnownChainIds.BitcoinMainnet]: 'btc', + [KnownChainIds.SolanaMainnet]: 'sol', + // TODO: Add Polkadot +} diff --git a/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts b/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts index ee88579f345..49c1474d3b0 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts @@ -1,26 +1,52 @@ -import {GetTradeQuoteInput, SwapErrorRight, SwapperDeps, TradeQuote, TradeQuoteError} from "../../../types"; -import {Err, Result} from "@sniptt/monads"; -import {makeSwapErrorRight} from "../../../utils"; -import {buySupportedChainIds, sellSupportedChainIds} from "../../ThorchainSwapper/constants"; +import { Err, Result } from "@sniptt/monads"; +import { KnownChainIds } from "@shapeshiftoss/types"; + +import { + GetTradeQuoteInput, + SwapErrorRight, + SwapperDeps, + TradeQuote, + TradeQuoteError +} from "../../../types"; +import { makeSwapErrorRight } from "../../../utils"; +import { chainIdToChainflipNetwork } from "../constants"; export const getChainflipTradeQuote = async ( input: GetTradeQuoteInput, deps: SwapperDeps, ): Promise> => { - const { sellAsset, buyAsset } = input + const { + sellAsset, + buyAsset, + // affiliateBps, + } = input + + // TODO: Add checking on support network and asset - if (!sellSupportedChainIds[sellAsset.chainId] || !buySupportedChainIds[buyAsset.chainId]) { - return Err( - makeSwapErrorRight({ - message: 'Unsupported chain', - code: TradeQuoteError.UnsupportedChain, - }), - ) - } + const sellChainflipChainKey = `${sellAsset.symbol.toLowerCase()}.${chainIdToChainflipNetwork[sellAsset.chainId as KnownChainIds]}`; + const buyChainflipChainKey = `${buyAsset.symbol.toLowerCase()}.${chainIdToChainflipNetwork[buyAsset.chainId as KnownChainIds]}`; + // if (sellChainflipChainKey === undefined) { + // return Err( + // makeSwapErrorRight({ + // message: `asset '${sellAsset.name}' on chainId '${sellAsset.chainId}' not supported`, + // code: TradeQuoteError.UnsupportedTradePair, + // }), + // ) + // } + // if (buyChainflipChainKey === undefined) { + // return Err( + // makeSwapErrorRight({ + // message: `asset '${buyAsset.name}' on chainId '${buyAsset.chainId}' not supported`, + // code: TradeQuoteError.UnsupportedTradePair, + // }), + // ) + // } + // @ts-ignore const brokerUrl = deps.config.REACT_APP_CHAINFLIP_API_URL // TODO: use the generated swagger client to get a quote + // TODO: How to get packages/unchained-client/dist/generated/chainflip in here? // TODO: Temp error return Err( From 8515f51dc532b81f64029ac4d9439c65291cf7d4 Mon Sep 17 00:00:00 2001 From: David Cumps Date: Wed, 23 Oct 2024 11:20:35 +0200 Subject: [PATCH 007/127] fix: dont add chainflip to unchained --- packages/unchained-client/openapitools.json | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/packages/unchained-client/openapitools.json b/packages/unchained-client/openapitools.json index ad218416a77..a8062c8f840 100644 --- a/packages/unchained-client/openapitools.json +++ b/packages/unchained-client/openapitools.json @@ -225,19 +225,6 @@ "supportsES6": "true", "useSingleRequestParameter": true } - }, - "chainflip": { - "inputSpec": "https://chainflip-broker.io/docs/v1/docs.json", - "generatorName": "typescript-fetch", - "output": "#{cwd}/src/generated/chainflip", - "enablePostProcessFile": true, - "reservedWordsMappings": { - "in": "in" - }, - "additionalProperties": { - "supportsES6": "true", - "useSingleRequestParameter": true - } } } } From c4131d51dbbd58766f245de1af7262d168f538ae Mon Sep 17 00:00:00 2001 From: David Cumps Date: Wed, 23 Oct 2024 11:28:56 +0200 Subject: [PATCH 008/127] feat: add supported chains and assets for chainflip --- .../getChainflipTradeQuote/getTradeQuote.ts | 65 +++++++++++++------ .../src/swappers/ChainflipSwapper/types.ts | 7 ++ .../ChainflipSwapper/utils/helpers.ts | 12 ++++ 3 files changed, 63 insertions(+), 21 deletions(-) create mode 100644 packages/swapper/src/swappers/ChainflipSwapper/utils/helpers.ts diff --git a/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts b/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts index 49c1474d3b0..5cd0dc5a603 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts @@ -10,6 +10,7 @@ import { } from "../../../types"; import { makeSwapErrorRight } from "../../../utils"; import { chainIdToChainflipNetwork } from "../constants"; +import { isSupportedChainId, isSupportedAsset } from "../utils/helpers"; export const getChainflipTradeQuote = async ( input: GetTradeQuoteInput, @@ -21,32 +22,54 @@ export const getChainflipTradeQuote = async ( // affiliateBps, } = input - // TODO: Add checking on support network and asset - + if (!isSupportedChainId(sellAsset.chainId)) { + return Err( + makeSwapErrorRight({ + message: `unsupported chainId`, + code: TradeQuoteError.UnsupportedChain, + details: { chainId: sellAsset.chainId }, + }), + ) + } + + if (!isSupportedChainId(buyAsset.chainId)) { + return Err( + makeSwapErrorRight({ + message: `unsupported chainId`, + code: TradeQuoteError.UnsupportedChain, + details: { chainId: sellAsset.chainId }, + }), + ) + } + + if (!isSupportedAsset(sellAsset.chainId, sellAsset.symbol)) { + return Err( + makeSwapErrorRight({ + message: `asset '${sellAsset.name}' on chainId '${sellAsset.chainId}' not supported`, + code: TradeQuoteError.UnsupportedTradePair, + details: { chainId: sellAsset.chainId, assetId: sellAsset.assetId }, + }), + ) + } + + if (!isSupportedAsset(buyAsset.chainId, buyAsset.symbol)) { + return Err( + makeSwapErrorRight({ + message: `asset '${buyAsset.name}' on chainId '${buyAsset.chainId}' not supported`, + code: TradeQuoteError.UnsupportedTradePair, + details: { chainId: buyAsset.chainId, assetId: buyAsset.assetId }, + }), + ) + } + + // @ts-ignore const sellChainflipChainKey = `${sellAsset.symbol.toLowerCase()}.${chainIdToChainflipNetwork[sellAsset.chainId as KnownChainIds]}`; + // @ts-ignore const buyChainflipChainKey = `${buyAsset.symbol.toLowerCase()}.${chainIdToChainflipNetwork[buyAsset.chainId as KnownChainIds]}`; - // if (sellChainflipChainKey === undefined) { - // return Err( - // makeSwapErrorRight({ - // message: `asset '${sellAsset.name}' on chainId '${sellAsset.chainId}' not supported`, - // code: TradeQuoteError.UnsupportedTradePair, - // }), - // ) - // } - // if (buyChainflipChainKey === undefined) { - // return Err( - // makeSwapErrorRight({ - // message: `asset '${buyAsset.name}' on chainId '${buyAsset.chainId}' not supported`, - // code: TradeQuoteError.UnsupportedTradePair, - // }), - // ) - // } - // @ts-ignore const brokerUrl = deps.config.REACT_APP_CHAINFLIP_API_URL - // TODO: use the generated swagger client to get a quote - // TODO: How to get packages/unchained-client/dist/generated/chainflip in here? + // TODO: Build the quote request // TODO: Temp error return Err( diff --git a/packages/swapper/src/swappers/ChainflipSwapper/types.ts b/packages/swapper/src/swappers/ChainflipSwapper/types.ts index d48c97f7248..24122596301 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/types.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/types.ts @@ -9,3 +9,10 @@ export const ChainflipSupportedChainIds = [ ] as const export type ChainflipSupportedChainId = (typeof ChainflipSupportedChainIds)[number] + +export const ChainflipSupportedAssets = { + [KnownChainIds.EthereumMainnet]: ['eth', 'flip', 'usdc', 'usdt'], + [KnownChainIds.ArbitrumMainnet]: ['arb', 'usdc'], + [KnownChainIds.BitcoinMainnet]: ['btc'], + [KnownChainIds.SolanaMainnet]: ['sol', 'usdc'], +} \ No newline at end of file diff --git a/packages/swapper/src/swappers/ChainflipSwapper/utils/helpers.ts b/packages/swapper/src/swappers/ChainflipSwapper/utils/helpers.ts new file mode 100644 index 00000000000..bf9d5856453 --- /dev/null +++ b/packages/swapper/src/swappers/ChainflipSwapper/utils/helpers.ts @@ -0,0 +1,12 @@ +import { type ChainId } from '@shapeshiftoss/caip' + +import type { ChainflipSupportedChainId } from '../types' +import { ChainflipSupportedChainIds, ChainflipSupportedAssets } from '../types' + +export const isSupportedChainId = (chainId: ChainId): chainId is ChainflipSupportedChainId => { + return ChainflipSupportedChainIds.includes(chainId as ChainflipSupportedChainId) +} + +export const isSupportedAsset = (chainId: ChainId, symbol: string): chainId is ChainflipSupportedChainId => { + return ChainflipSupportedAssets[chainId as ChainflipSupportedChainId].includes(symbol.toLowerCase()) +} \ No newline at end of file From 159650a8de7158d3a9a449881a541b3a161a3219 Mon Sep 17 00:00:00 2001 From: David Cumps Date: Wed, 23 Oct 2024 12:57:13 +0200 Subject: [PATCH 009/127] feat: add chainflip csp --- react-app-rewired/headers/csps/chainflip.ts | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 react-app-rewired/headers/csps/chainflip.ts diff --git a/react-app-rewired/headers/csps/chainflip.ts b/react-app-rewired/headers/csps/chainflip.ts new file mode 100644 index 00000000000..8030940e5f4 --- /dev/null +++ b/react-app-rewired/headers/csps/chainflip.ts @@ -0,0 +1,7 @@ +import type { Csp } from '../types' + +export const csp: Csp = { + 'connect-src': [ + 'https://chainflip-broker.io/', + ], +} From cca5688388642424bdb8a979953bca1d0f7816d3 Mon Sep 17 00:00:00 2001 From: David Cumps Date: Wed, 23 Oct 2024 12:57:49 +0200 Subject: [PATCH 010/127] feat: fetch chainflip quote --- .../getChainflipTradeQuote/getTradeQuote.ts | 34 ++- .../models/ChainflipBaasAssetsAssetInfo.ts | 169 ++++++++++++ .../ChainflipBaasAssetsAssetsResponse.ts | 72 ++++++ .../ChainflipBaasBalanceBalanceResponse.ts | 72 ++++++ .../models/ChainflipBaasFeesFeesResponse.ts | 72 ++++++ .../ChainflipBaasNetworksNetworkInfo.ts | 79 ++++++ .../ChainflipBaasNetworksNetworksResponse.ts | 72 ++++++ .../models/ChainflipBaasQuoteBoostQuote.ts | 168 ++++++++++++ .../models/ChainflipBaasQuotePoolFee.ts | 82 ++++++ .../models/ChainflipBaasQuotePoolInfo.ts | 89 +++++++ .../models/ChainflipBaasQuoteQuote.ts | 193 ++++++++++++++ .../models/ChainflipBaasQuoteQuoteFee.ts | 105 ++++++++ .../models/ChainflipBaasRpcRpcRequest.ts | 104 ++++++++ .../ChainflipBaasStatusAffiliateBroker.ts | 72 ++++++ .../models/ChainflipBaasStatusBoost.ts | 114 ++++++++ .../ChainflipBaasStatusCcmParameters.ts | 79 ++++++ .../models/ChainflipBaasStatusChunkInfo.ts | 149 +++++++++++ .../models/ChainflipBaasStatusDca.ts | 95 +++++++ .../ChainflipBaasStatusDcaParameters.ts | 72 ++++++ .../models/ChainflipBaasStatusDeposit.ts | 143 +++++++++++ .../ChainflipBaasStatusDepositChannel.ts | 184 +++++++++++++ .../models/ChainflipBaasStatusEgress.ts | 150 +++++++++++ .../models/ChainflipBaasStatusFailure.ts | 101 ++++++++ ...ChainflipBaasStatusFillOrKillParameters.ts | 79 ++++++ .../models/ChainflipBaasStatusPaidFee.ts | 101 ++++++++ .../models/ChainflipBaasStatusReason.ts | 72 ++++++ .../ChainflipBaasStatusStatusResponse.ts | 81 ++++++ .../models/ChainflipBaasStatusSwap.ts | 167 ++++++++++++ .../models/ChainflipBaasStatusSwapStatus.ts | 243 ++++++++++++++++++ .../ChainflipBaasSwapAdvancedSwapRequest.ts | 73 ++++++ .../models/ChainflipBaasSwapCcmRequest.ts | 76 ++++++ .../models/ChainflipBaasSwapDepositAddress.ts | 122 +++++++++ .../MicrosoftAspNetCoreMvcProblemDetails.ts | 101 ++++++++ ...ftAspNetCoreMvcValidationProblemDetails.ts | 109 ++++++++ .../swappers/ChainflipSwapper/models/index.ts | 36 +++ .../utils/chainflipService.ts | 19 ++ packages/swapper/src/types.ts | 1 + 37 files changed, 3736 insertions(+), 14 deletions(-) create mode 100644 packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasAssetsAssetInfo.ts create mode 100644 packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasAssetsAssetsResponse.ts create mode 100644 packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasBalanceBalanceResponse.ts create mode 100644 packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasFeesFeesResponse.ts create mode 100644 packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasNetworksNetworkInfo.ts create mode 100644 packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasNetworksNetworksResponse.ts create mode 100644 packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasQuoteBoostQuote.ts create mode 100644 packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasQuotePoolFee.ts create mode 100644 packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasQuotePoolInfo.ts create mode 100644 packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasQuoteQuote.ts create mode 100644 packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasQuoteQuoteFee.ts create mode 100644 packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasRpcRpcRequest.ts create mode 100644 packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusAffiliateBroker.ts create mode 100644 packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusBoost.ts create mode 100644 packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusCcmParameters.ts create mode 100644 packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusChunkInfo.ts create mode 100644 packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusDca.ts create mode 100644 packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusDcaParameters.ts create mode 100644 packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusDeposit.ts create mode 100644 packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusDepositChannel.ts create mode 100644 packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusEgress.ts create mode 100644 packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusFailure.ts create mode 100644 packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusFillOrKillParameters.ts create mode 100644 packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusPaidFee.ts create mode 100644 packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusReason.ts create mode 100644 packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusStatusResponse.ts create mode 100644 packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusSwap.ts create mode 100644 packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusSwapStatus.ts create mode 100644 packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasSwapAdvancedSwapRequest.ts create mode 100644 packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasSwapCcmRequest.ts create mode 100644 packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasSwapDepositAddress.ts create mode 100644 packages/swapper/src/swappers/ChainflipSwapper/models/MicrosoftAspNetCoreMvcProblemDetails.ts create mode 100644 packages/swapper/src/swappers/ChainflipSwapper/models/MicrosoftAspNetCoreMvcValidationProblemDetails.ts create mode 100644 packages/swapper/src/swappers/ChainflipSwapper/models/index.ts create mode 100644 packages/swapper/src/swappers/ChainflipSwapper/utils/chainflipService.ts diff --git a/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts b/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts index 5cd0dc5a603..9a7f7e53516 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts @@ -11,6 +11,8 @@ import { import { makeSwapErrorRight } from "../../../utils"; import { chainIdToChainflipNetwork } from "../constants"; import { isSupportedChainId, isSupportedAsset } from "../utils/helpers"; +import { chainflipService } from "../utils/chainflipService"; +import { ChainflipBaasQuoteQuote } from "../models"; export const getChainflipTradeQuote = async ( input: GetTradeQuoteInput, @@ -18,8 +20,9 @@ export const getChainflipTradeQuote = async ( ): Promise> => { const { sellAsset, - buyAsset, - // affiliateBps, + buyAsset, + sellAmountIncludingProtocolFeesCryptoBaseUnit: sellAmount, + affiliateBps: commissionBps, } = input if (!isSupportedChainId(sellAsset.chainId)) { @@ -62,20 +65,23 @@ export const getChainflipTradeQuote = async ( ) } - // @ts-ignore const sellChainflipChainKey = `${sellAsset.symbol.toLowerCase()}.${chainIdToChainflipNetwork[sellAsset.chainId as KnownChainIds]}`; - // @ts-ignore const buyChainflipChainKey = `${buyAsset.symbol.toLowerCase()}.${chainIdToChainflipNetwork[buyAsset.chainId as KnownChainIds]}`; - // @ts-ignore const brokerUrl = deps.config.REACT_APP_CHAINFLIP_API_URL - // TODO: Build the quote request - - // TODO: Temp error - return Err( - makeSwapErrorRight({ - message: 'Unsupported chain', - code: TradeQuoteError.UnsupportedChain, - }), - ) + const apiKey = deps.config.REACT_APP_CHAINFLIP_API_KEY; + + // @ts-ignore + const maybeQuoteResponse = await chainflipService.get( + `${brokerUrl}/quotes-native?apiKey=${apiKey}&sourceAsset=${sellChainflipChainKey}&destinationAsset=${buyChainflipChainKey}&amount=${sellAmount}&commissionBps=${commissionBps}`, + ); + + //if (maybeQuoteResponse.isErr()) { + return Err( + makeSwapErrorRight({ + message: 'Quote request failed', + code: TradeQuoteError.NoRouteFound, + }), + ) + //} } \ No newline at end of file diff --git a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasAssetsAssetInfo.ts b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasAssetsAssetInfo.ts new file mode 100644 index 00000000000..92027e8fd91 --- /dev/null +++ b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasAssetsAssetInfo.ts @@ -0,0 +1,169 @@ +// @ts-nocheck +/* tslint:disable */ +/* eslint-disable */ +/** + * Chainflip Broker as a Service + * Run your own Chainflip Broker without any hassle. + * + * The version of the OpenAPI document: v1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +/** + * + * @export + * @interface ChainflipBaasAssetsAssetInfo + */ +export interface ChainflipBaasAssetsAssetInfo { + /** + * Unique id of the asset. + * @type {string} + * @memberof ChainflipBaasAssetsAssetInfo + */ + id?: string; + /** + * Direction an asset can be used in. Ingress assets can only be used to swap from. Egress assets can only be used to swap to. Assets with both can be used to swap from and to. + * @type {string} + * @memberof ChainflipBaasAssetsAssetInfo + */ + direction?: ChainflipBaasAssetsAssetInfoDirectionEnum; + /** + * Display ticker of the asset. + * @type {string} + * @memberof ChainflipBaasAssetsAssetInfo + */ + ticker?: string; + /** + * Descriptive name of the asset. + * @type {string} + * @memberof ChainflipBaasAssetsAssetInfo + */ + name?: string; + /** + * Name of the network where the asset is located. + * @type {string} + * @memberof ChainflipBaasAssetsAssetInfo + */ + network?: string; + /** + * The contract address for tokens which have one. + * @type {string} + * @memberof ChainflipBaasAssetsAssetInfo + */ + contractAddress?: string | null; + /** + * A url to the logo for the network. + * @type {string} + * @memberof ChainflipBaasAssetsAssetInfo + */ + readonly networkLogo?: string; + /** + * A url to the logo for the asset. + * @type {string} + * @memberof ChainflipBaasAssetsAssetInfo + */ + readonly assetLogo?: string; + /** + * Number of decimals the asset native value contains. + * @type {number} + * @memberof ChainflipBaasAssetsAssetInfo + */ + decimals?: number; + /** + * Minimum amount required to swap the asset. + * @type {number} + * @memberof ChainflipBaasAssetsAssetInfo + */ + minimalAmount?: number; + /** + * Minimum amount in native units required to swap the asset. + * @type {string} + * @memberof ChainflipBaasAssetsAssetInfo + */ + readonly minimalAmountNative?: string; + /** + * Current pool price of the asset in USDC. + * @type {number} + * @memberof ChainflipBaasAssetsAssetInfo + */ + readonly usdPrice?: number | null; + /** + * Current pool price of the asset in USDC native units. + * @type {string} + * @memberof ChainflipBaasAssetsAssetInfo + */ + readonly usdPriceNative?: string | null; +} + + +/** + * @export + */ +export const ChainflipBaasAssetsAssetInfoDirectionEnum = { + Ingress: 'ingress', + Egress: 'egress', + Both: 'both' +} as const; +export type ChainflipBaasAssetsAssetInfoDirectionEnum = typeof ChainflipBaasAssetsAssetInfoDirectionEnum[keyof typeof ChainflipBaasAssetsAssetInfoDirectionEnum]; + + +/** + * Check if a given object implements the ChainflipBaasAssetsAssetInfo interface. + */ +export function instanceOfChainflipBaasAssetsAssetInfo(value: object): boolean { + let isInstance = true; + + return isInstance; +} + +export function ChainflipBaasAssetsAssetInfoFromJSON(json: any): ChainflipBaasAssetsAssetInfo { + return ChainflipBaasAssetsAssetInfoFromJSONTyped(json, false); +} + +export function ChainflipBaasAssetsAssetInfoFromJSONTyped(json: any, ignoreDiscriminator: boolean): ChainflipBaasAssetsAssetInfo { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'id': !exists(json, 'id') ? undefined : json['id'], + 'direction': !exists(json, 'direction') ? undefined : json['direction'], + 'ticker': !exists(json, 'ticker') ? undefined : json['ticker'], + 'name': !exists(json, 'name') ? undefined : json['name'], + 'network': !exists(json, 'network') ? undefined : json['network'], + 'contractAddress': !exists(json, 'contractAddress') ? undefined : json['contractAddress'], + 'networkLogo': !exists(json, 'networkLogo') ? undefined : json['networkLogo'], + 'assetLogo': !exists(json, 'assetLogo') ? undefined : json['assetLogo'], + 'decimals': !exists(json, 'decimals') ? undefined : json['decimals'], + 'minimalAmount': !exists(json, 'minimalAmount') ? undefined : json['minimalAmount'], + 'minimalAmountNative': !exists(json, 'minimalAmountNative') ? undefined : json['minimalAmountNative'], + 'usdPrice': !exists(json, 'usdPrice') ? undefined : json['usdPrice'], + 'usdPriceNative': !exists(json, 'usdPriceNative') ? undefined : json['usdPriceNative'], + }; +} + +export function ChainflipBaasAssetsAssetInfoToJSON(value?: ChainflipBaasAssetsAssetInfo | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'id': value.id, + 'direction': value.direction, + 'ticker': value.ticker, + 'name': value.name, + 'network': value.network, + 'contractAddress': value.contractAddress, + 'decimals': value.decimals, + 'minimalAmount': value.minimalAmount, + }; +} + diff --git a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasAssetsAssetsResponse.ts b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasAssetsAssetsResponse.ts new file mode 100644 index 00000000000..59a0cd2ccc4 --- /dev/null +++ b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasAssetsAssetsResponse.ts @@ -0,0 +1,72 @@ +// @ts-nocheck +/* tslint:disable */ +/* eslint-disable */ +/** + * Chainflip Broker as a Service + * Run your own Chainflip Broker without any hassle. + * + * The version of the OpenAPI document: v1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +import type { ChainflipBaasAssetsAssetInfo } from './ChainflipBaasAssetsAssetInfo'; +import { + ChainflipBaasAssetsAssetInfoFromJSON, + ChainflipBaasAssetsAssetInfoFromJSONTyped, + ChainflipBaasAssetsAssetInfoToJSON, +} from './ChainflipBaasAssetsAssetInfo'; + +/** + * + * @export + * @interface ChainflipBaasAssetsAssetsResponse + */ +export interface ChainflipBaasAssetsAssetsResponse { + /** + * All available assets. + * @type {Array} + * @memberof ChainflipBaasAssetsAssetsResponse + */ + readonly assets?: Array; +} + +/** + * Check if a given object implements the ChainflipBaasAssetsAssetsResponse interface. + */ +export function instanceOfChainflipBaasAssetsAssetsResponse(value: object): boolean { + let isInstance = true; + + return isInstance; +} + +export function ChainflipBaasAssetsAssetsResponseFromJSON(json: any): ChainflipBaasAssetsAssetsResponse { + return ChainflipBaasAssetsAssetsResponseFromJSONTyped(json, false); +} + +export function ChainflipBaasAssetsAssetsResponseFromJSONTyped(json: any, ignoreDiscriminator: boolean): ChainflipBaasAssetsAssetsResponse { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'assets': !exists(json, 'assets') ? undefined : ((json['assets'] as Array).map(ChainflipBaasAssetsAssetInfoFromJSON)), + }; +} + +export function ChainflipBaasAssetsAssetsResponseToJSON(value?: ChainflipBaasAssetsAssetsResponse | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + }; +} + diff --git a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasBalanceBalanceResponse.ts b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasBalanceBalanceResponse.ts new file mode 100644 index 00000000000..4fad00479ff --- /dev/null +++ b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasBalanceBalanceResponse.ts @@ -0,0 +1,72 @@ +// @ts-nocheck +/* tslint:disable */ +/* eslint-disable */ +/** + * Chainflip Broker as a Service + * Run your own Chainflip Broker without any hassle. + * + * The version of the OpenAPI document: v1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +/** + * + * @export + * @interface ChainflipBaasBalanceBalanceResponse + */ +export interface ChainflipBaasBalanceBalanceResponse { + /** + * Current FLIP balance + * @type {number} + * @memberof ChainflipBaasBalanceBalanceResponse + */ + readonly currentBalance?: number; + /** + * Current FLIP balance in flipperinos. + * @type {string} + * @memberof ChainflipBaasBalanceBalanceResponse + */ + readonly currentBalanceNative?: string; +} + +/** + * Check if a given object implements the ChainflipBaasBalanceBalanceResponse interface. + */ +export function instanceOfChainflipBaasBalanceBalanceResponse(value: object): boolean { + let isInstance = true; + + return isInstance; +} + +export function ChainflipBaasBalanceBalanceResponseFromJSON(json: any): ChainflipBaasBalanceBalanceResponse { + return ChainflipBaasBalanceBalanceResponseFromJSONTyped(json, false); +} + +export function ChainflipBaasBalanceBalanceResponseFromJSONTyped(json: any, ignoreDiscriminator: boolean): ChainflipBaasBalanceBalanceResponse { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'currentBalance': !exists(json, 'currentBalance') ? undefined : json['currentBalance'], + 'currentBalanceNative': !exists(json, 'currentBalanceNative') ? undefined : json['currentBalanceNative'], + }; +} + +export function ChainflipBaasBalanceBalanceResponseToJSON(value?: ChainflipBaasBalanceBalanceResponse | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + }; +} + diff --git a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasFeesFeesResponse.ts b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasFeesFeesResponse.ts new file mode 100644 index 00000000000..7fde4c1d0bb --- /dev/null +++ b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasFeesFeesResponse.ts @@ -0,0 +1,72 @@ +// @ts-nocheck +/* tslint:disable */ +/* eslint-disable */ +/** + * Chainflip Broker as a Service + * Run your own Chainflip Broker without any hassle. + * + * The version of the OpenAPI document: v1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +/** + * + * @export + * @interface ChainflipBaasFeesFeesResponse + */ +export interface ChainflipBaasFeesFeesResponse { + /** + * Earned broker fees per asset. + * @type {{ [key: string]: number; }} + * @memberof ChainflipBaasFeesFeesResponse + */ + readonly earnedFees?: { [key: string]: number; }; + /** + * Earned broker fees per asset in native units. + * @type {{ [key: string]: string; }} + * @memberof ChainflipBaasFeesFeesResponse + */ + readonly earnedFeesNative?: { [key: string]: string; }; +} + +/** + * Check if a given object implements the ChainflipBaasFeesFeesResponse interface. + */ +export function instanceOfChainflipBaasFeesFeesResponse(value: object): boolean { + let isInstance = true; + + return isInstance; +} + +export function ChainflipBaasFeesFeesResponseFromJSON(json: any): ChainflipBaasFeesFeesResponse { + return ChainflipBaasFeesFeesResponseFromJSONTyped(json, false); +} + +export function ChainflipBaasFeesFeesResponseFromJSONTyped(json: any, ignoreDiscriminator: boolean): ChainflipBaasFeesFeesResponse { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'earnedFees': !exists(json, 'earnedFees') ? undefined : json['earnedFees'], + 'earnedFeesNative': !exists(json, 'earnedFeesNative') ? undefined : json['earnedFeesNative'], + }; +} + +export function ChainflipBaasFeesFeesResponseToJSON(value?: ChainflipBaasFeesFeesResponse | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + }; +} + diff --git a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasNetworksNetworkInfo.ts b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasNetworksNetworkInfo.ts new file mode 100644 index 00000000000..0a3d88925da --- /dev/null +++ b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasNetworksNetworkInfo.ts @@ -0,0 +1,79 @@ +// @ts-nocheck +/* tslint:disable */ +/* eslint-disable */ +/** + * Chainflip Broker as a Service + * Run your own Chainflip Broker without any hassle. + * + * The version of the OpenAPI document: v1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +/** + * + * @export + * @interface ChainflipBaasNetworksNetworkInfo + */ +export interface ChainflipBaasNetworksNetworkInfo { + /** + * Network id. + * @type {string} + * @memberof ChainflipBaasNetworksNetworkInfo + */ + readonly id?: string; + /** + * Network name. + * @type {string} + * @memberof ChainflipBaasNetworksNetworkInfo + */ + readonly name?: string; + /** + * A url to the logo for the network. + * @type {string} + * @memberof ChainflipBaasNetworksNetworkInfo + */ + readonly logo?: string; +} + +/** + * Check if a given object implements the ChainflipBaasNetworksNetworkInfo interface. + */ +export function instanceOfChainflipBaasNetworksNetworkInfo(value: object): boolean { + let isInstance = true; + + return isInstance; +} + +export function ChainflipBaasNetworksNetworkInfoFromJSON(json: any): ChainflipBaasNetworksNetworkInfo { + return ChainflipBaasNetworksNetworkInfoFromJSONTyped(json, false); +} + +export function ChainflipBaasNetworksNetworkInfoFromJSONTyped(json: any, ignoreDiscriminator: boolean): ChainflipBaasNetworksNetworkInfo { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'id': !exists(json, 'id') ? undefined : json['id'], + 'name': !exists(json, 'name') ? undefined : json['name'], + 'logo': !exists(json, 'logo') ? undefined : json['logo'], + }; +} + +export function ChainflipBaasNetworksNetworkInfoToJSON(value?: ChainflipBaasNetworksNetworkInfo | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + }; +} + diff --git a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasNetworksNetworksResponse.ts b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasNetworksNetworksResponse.ts new file mode 100644 index 00000000000..87c7b21dc7f --- /dev/null +++ b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasNetworksNetworksResponse.ts @@ -0,0 +1,72 @@ +// @ts-nocheck +/* tslint:disable */ +/* eslint-disable */ +/** + * Chainflip Broker as a Service + * Run your own Chainflip Broker without any hassle. + * + * The version of the OpenAPI document: v1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +import type { ChainflipBaasNetworksNetworkInfo } from './ChainflipBaasNetworksNetworkInfo'; +import { + ChainflipBaasNetworksNetworkInfoFromJSON, + ChainflipBaasNetworksNetworkInfoFromJSONTyped, + ChainflipBaasNetworksNetworkInfoToJSON, +} from './ChainflipBaasNetworksNetworkInfo'; + +/** + * + * @export + * @interface ChainflipBaasNetworksNetworksResponse + */ +export interface ChainflipBaasNetworksNetworksResponse { + /** + * All available networks. + * @type {Array} + * @memberof ChainflipBaasNetworksNetworksResponse + */ + readonly networks?: Array; +} + +/** + * Check if a given object implements the ChainflipBaasNetworksNetworksResponse interface. + */ +export function instanceOfChainflipBaasNetworksNetworksResponse(value: object): boolean { + let isInstance = true; + + return isInstance; +} + +export function ChainflipBaasNetworksNetworksResponseFromJSON(json: any): ChainflipBaasNetworksNetworksResponse { + return ChainflipBaasNetworksNetworksResponseFromJSONTyped(json, false); +} + +export function ChainflipBaasNetworksNetworksResponseFromJSONTyped(json: any, ignoreDiscriminator: boolean): ChainflipBaasNetworksNetworksResponse { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'networks': !exists(json, 'networks') ? undefined : ((json['networks'] as Array).map(ChainflipBaasNetworksNetworkInfoFromJSON)), + }; +} + +export function ChainflipBaasNetworksNetworksResponseToJSON(value?: ChainflipBaasNetworksNetworksResponse | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + }; +} + diff --git a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasQuoteBoostQuote.ts b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasQuoteBoostQuote.ts new file mode 100644 index 00000000000..268ac2ea76b --- /dev/null +++ b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasQuoteBoostQuote.ts @@ -0,0 +1,168 @@ +// @ts-nocheck +/* tslint:disable */ +/* eslint-disable */ +/** + * Chainflip Broker as a Service + * Run your own Chainflip Broker without any hassle. + * + * The version of the OpenAPI document: v1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +import type { ChainflipBaasQuotePoolInfo } from './ChainflipBaasQuotePoolInfo'; +import { + ChainflipBaasQuotePoolInfoFromJSON, + ChainflipBaasQuotePoolInfoFromJSONTyped, + ChainflipBaasQuotePoolInfoToJSON, +} from './ChainflipBaasQuotePoolInfo'; +import type { ChainflipBaasQuoteQuoteFee } from './ChainflipBaasQuoteQuoteFee'; +import { + ChainflipBaasQuoteQuoteFeeFromJSON, + ChainflipBaasQuoteQuoteFeeFromJSONTyped, + ChainflipBaasQuoteQuoteFeeToJSON, +} from './ChainflipBaasQuoteQuoteFee'; + +/** + * An optional quote to have the swap boosted. + * @export + * @interface ChainflipBaasQuoteBoostQuote + */ +export interface ChainflipBaasQuoteBoostQuote { + /** + * The asset to send. + * @type {string} + * @memberof ChainflipBaasQuoteBoostQuote + */ + ingressAsset?: string; + /** + * The amount to send. + * @type {number} + * @memberof ChainflipBaasQuoteBoostQuote + */ + ingressAmount?: number; + /** + * The amount to send in native units. + * @type {string} + * @memberof ChainflipBaasQuoteBoostQuote + */ + readonly ingressAmountNative?: string; + /** + * The asset to receive. + * @type {string} + * @memberof ChainflipBaasQuoteBoostQuote + */ + egressAsset?: string; + /** + * The amount to receive. + * @type {number} + * @memberof ChainflipBaasQuoteBoostQuote + */ + readonly egressAmount?: number; + /** + * The amount to receive in native units. + * @type {string} + * @memberof ChainflipBaasQuoteBoostQuote + */ + readonly egressAmountNative?: string; + /** + * The fee structure, this includes all fees. + * @type {Array} + * @memberof ChainflipBaasQuoteBoostQuote + */ + readonly includedFees?: Array; + /** + * A warning in case liquidity is low and there is a risk of high slippage. + * @type {boolean} + * @memberof ChainflipBaasQuoteBoostQuote + */ + readonly lowLiquidityWarning?: boolean; + /** + * Liquidity pools involved in the swap, as well as estimated liquidity provider fees. + * @type {Array} + * @memberof ChainflipBaasQuoteBoostQuote + */ + poolInfo?: Array; + /** + * The estimated time the swap will take. + * @type {number} + * @memberof ChainflipBaasQuoteBoostQuote + */ + readonly estimatedDurationSeconds?: number; + /** + * The estimated fee (in bps) that the user has to pay (from the deposit amount) to get this swap boosted. + * @type {number} + * @memberof ChainflipBaasQuoteBoostQuote + */ + readonly estimatedBoostFeeBps?: number; + /** + * The number of "sub-swaps" to perform for a DCA swap. + * @type {number} + * @memberof ChainflipBaasQuoteBoostQuote + */ + chunkIntervalBlocks?: number | null; + /** + * The delay between the "sub-swaps" of a DCA swap in number of blocks. + * @type {number} + * @memberof ChainflipBaasQuoteBoostQuote + */ + numberOfChunks?: number | null; +} + +/** + * Check if a given object implements the ChainflipBaasQuoteBoostQuote interface. + */ +export function instanceOfChainflipBaasQuoteBoostQuote(value: object): boolean { + let isInstance = true; + + return isInstance; +} + +export function ChainflipBaasQuoteBoostQuoteFromJSON(json: any): ChainflipBaasQuoteBoostQuote { + return ChainflipBaasQuoteBoostQuoteFromJSONTyped(json, false); +} + +export function ChainflipBaasQuoteBoostQuoteFromJSONTyped(json: any, ignoreDiscriminator: boolean): ChainflipBaasQuoteBoostQuote { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'ingressAsset': !exists(json, 'ingressAsset') ? undefined : json['ingressAsset'], + 'ingressAmount': !exists(json, 'ingressAmount') ? undefined : json['ingressAmount'], + 'ingressAmountNative': !exists(json, 'ingressAmountNative') ? undefined : json['ingressAmountNative'], + 'egressAsset': !exists(json, 'egressAsset') ? undefined : json['egressAsset'], + 'egressAmount': !exists(json, 'egressAmount') ? undefined : json['egressAmount'], + 'egressAmountNative': !exists(json, 'egressAmountNative') ? undefined : json['egressAmountNative'], + 'includedFees': !exists(json, 'includedFees') ? undefined : ((json['includedFees'] as Array).map(ChainflipBaasQuoteQuoteFeeFromJSON)), + 'lowLiquidityWarning': !exists(json, 'lowLiquidityWarning') ? undefined : json['lowLiquidityWarning'], + 'poolInfo': !exists(json, 'poolInfo') ? undefined : ((json['poolInfo'] as Array).map(ChainflipBaasQuotePoolInfoFromJSON)), + 'estimatedDurationSeconds': !exists(json, 'estimatedDurationSeconds') ? undefined : json['estimatedDurationSeconds'], + 'estimatedBoostFeeBps': !exists(json, 'estimatedBoostFeeBps') ? undefined : json['estimatedBoostFeeBps'], + 'chunkIntervalBlocks': !exists(json, 'chunkIntervalBlocks') ? undefined : json['chunkIntervalBlocks'], + 'numberOfChunks': !exists(json, 'numberOfChunks') ? undefined : json['numberOfChunks'], + }; +} + +export function ChainflipBaasQuoteBoostQuoteToJSON(value?: ChainflipBaasQuoteBoostQuote | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'ingressAsset': value.ingressAsset, + 'ingressAmount': value.ingressAmount, + 'egressAsset': value.egressAsset, + 'poolInfo': value.poolInfo === undefined ? undefined : ((value.poolInfo as Array).map(ChainflipBaasQuotePoolInfoToJSON)), + 'chunkIntervalBlocks': value.chunkIntervalBlocks, + 'numberOfChunks': value.numberOfChunks, + }; +} + diff --git a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasQuotePoolFee.ts b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasQuotePoolFee.ts new file mode 100644 index 00000000000..cb881a98c03 --- /dev/null +++ b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasQuotePoolFee.ts @@ -0,0 +1,82 @@ +// @ts-nocheck +/* tslint:disable */ +/* eslint-disable */ +/** + * Chainflip Broker as a Service + * Run your own Chainflip Broker without any hassle. + * + * The version of the OpenAPI document: v1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +/** + * + * @export + * @interface ChainflipBaasQuotePoolFee + */ +export interface ChainflipBaasQuotePoolFee { + /** + * The asset the fee is processed in. + * @type {string} + * @memberof ChainflipBaasQuotePoolFee + */ + asset?: string | null; + /** + * The fee amount. + * @type {number} + * @memberof ChainflipBaasQuotePoolFee + */ + amount?: number; + /** + * The fee amount in native units. + * @type {string} + * @memberof ChainflipBaasQuotePoolFee + */ + amountNative?: string; +} + +/** + * Check if a given object implements the ChainflipBaasQuotePoolFee interface. + */ +export function instanceOfChainflipBaasQuotePoolFee(value: object): boolean { + let isInstance = true; + + return isInstance; +} + +export function ChainflipBaasQuotePoolFeeFromJSON(json: any): ChainflipBaasQuotePoolFee { + return ChainflipBaasQuotePoolFeeFromJSONTyped(json, false); +} + +export function ChainflipBaasQuotePoolFeeFromJSONTyped(json: any, ignoreDiscriminator: boolean): ChainflipBaasQuotePoolFee { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'asset': !exists(json, 'asset') ? undefined : json['asset'], + 'amount': !exists(json, 'amount') ? undefined : json['amount'], + 'amountNative': !exists(json, 'amountNative') ? undefined : json['amountNative'], + }; +} + +export function ChainflipBaasQuotePoolFeeToJSON(value?: ChainflipBaasQuotePoolFee | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'asset': value.asset, + 'amount': value.amount, + 'amountNative': value.amountNative, + }; +} + diff --git a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasQuotePoolInfo.ts b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasQuotePoolInfo.ts new file mode 100644 index 00000000000..6f499f241ea --- /dev/null +++ b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasQuotePoolInfo.ts @@ -0,0 +1,89 @@ +// @ts-nocheck +/* tslint:disable */ +/* eslint-disable */ +/** + * Chainflip Broker as a Service + * Run your own Chainflip Broker without any hassle. + * + * The version of the OpenAPI document: v1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +import type { ChainflipBaasQuotePoolFee } from './ChainflipBaasQuotePoolFee'; +import { + ChainflipBaasQuotePoolFeeFromJSON, + ChainflipBaasQuotePoolFeeFromJSONTyped, + ChainflipBaasQuotePoolFeeToJSON, +} from './ChainflipBaasQuotePoolFee'; + +/** + * + * @export + * @interface ChainflipBaasQuotePoolInfo + */ +export interface ChainflipBaasQuotePoolInfo { + /** + * The base asset of the pool involved. + * @type {string} + * @memberof ChainflipBaasQuotePoolInfo + */ + baseAsset?: string; + /** + * The quote asset of the pool involved. + * @type {string} + * @memberof ChainflipBaasQuotePoolInfo + */ + quoteAsset?: string; + /** + * + * @type {ChainflipBaasQuotePoolFee} + * @memberof ChainflipBaasQuotePoolInfo + */ + fee?: ChainflipBaasQuotePoolFee; +} + +/** + * Check if a given object implements the ChainflipBaasQuotePoolInfo interface. + */ +export function instanceOfChainflipBaasQuotePoolInfo(value: object): boolean { + let isInstance = true; + + return isInstance; +} + +export function ChainflipBaasQuotePoolInfoFromJSON(json: any): ChainflipBaasQuotePoolInfo { + return ChainflipBaasQuotePoolInfoFromJSONTyped(json, false); +} + +export function ChainflipBaasQuotePoolInfoFromJSONTyped(json: any, ignoreDiscriminator: boolean): ChainflipBaasQuotePoolInfo { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'baseAsset': !exists(json, 'baseAsset') ? undefined : json['baseAsset'], + 'quoteAsset': !exists(json, 'quoteAsset') ? undefined : json['quoteAsset'], + 'fee': !exists(json, 'fee') ? undefined : ChainflipBaasQuotePoolFeeFromJSON(json['fee']), + }; +} + +export function ChainflipBaasQuotePoolInfoToJSON(value?: ChainflipBaasQuotePoolInfo | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'baseAsset': value.baseAsset, + 'quoteAsset': value.quoteAsset, + 'fee': ChainflipBaasQuotePoolFeeToJSON(value.fee), + }; +} + diff --git a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasQuoteQuote.ts b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasQuoteQuote.ts new file mode 100644 index 00000000000..24ce7d7e52a --- /dev/null +++ b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasQuoteQuote.ts @@ -0,0 +1,193 @@ +// @ts-nocheck +/* tslint:disable */ +/* eslint-disable */ +/** + * Chainflip Broker as a Service + * Run your own Chainflip Broker without any hassle. + * + * The version of the OpenAPI document: v1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +import type { ChainflipBaasQuoteBoostQuote } from './ChainflipBaasQuoteBoostQuote'; +import { + ChainflipBaasQuoteBoostQuoteFromJSON, + ChainflipBaasQuoteBoostQuoteFromJSONTyped, + ChainflipBaasQuoteBoostQuoteToJSON, +} from './ChainflipBaasQuoteBoostQuote'; +import type { ChainflipBaasQuotePoolInfo } from './ChainflipBaasQuotePoolInfo'; +import { + ChainflipBaasQuotePoolInfoFromJSON, + ChainflipBaasQuotePoolInfoFromJSONTyped, + ChainflipBaasQuotePoolInfoToJSON, +} from './ChainflipBaasQuotePoolInfo'; +import type { ChainflipBaasQuoteQuoteFee } from './ChainflipBaasQuoteQuoteFee'; +import { + ChainflipBaasQuoteQuoteFeeFromJSON, + ChainflipBaasQuoteQuoteFeeFromJSONTyped, + ChainflipBaasQuoteQuoteFeeToJSON, +} from './ChainflipBaasQuoteQuoteFee'; + +/** + * + * @export + * @interface ChainflipBaasQuoteQuote + */ +export interface ChainflipBaasQuoteQuote { + /** + * The type of quote. + * @type {string} + * @memberof ChainflipBaasQuoteQuote + */ + readonly type?: ChainflipBaasQuoteQuoteTypeEnum; + /** + * The asset to send. + * @type {string} + * @memberof ChainflipBaasQuoteQuote + */ + ingressAsset?: string; + /** + * The amount to send. + * @type {number} + * @memberof ChainflipBaasQuoteQuote + */ + ingressAmount?: number; + /** + * The amount to send in native units. + * @type {string} + * @memberof ChainflipBaasQuoteQuote + */ + readonly ingressAmountNative?: string; + /** + * The asset to receive. + * @type {string} + * @memberof ChainflipBaasQuoteQuote + */ + egressAsset?: string; + /** + * The amount to receive. + * @type {number} + * @memberof ChainflipBaasQuoteQuote + */ + readonly egressAmount?: number; + /** + * The amount to receive in native units. + * @type {string} + * @memberof ChainflipBaasQuoteQuote + */ + readonly egressAmountNative?: string; + /** + * The fee structure, this includes all fees. + * @type {Array} + * @memberof ChainflipBaasQuoteQuote + */ + readonly includedFees?: Array; + /** + * A warning in case liquidity is low and there is a risk of high slippage. + * @type {boolean} + * @memberof ChainflipBaasQuoteQuote + */ + readonly lowLiquidityWarning?: boolean; + /** + * Liquidity pools involved in the swap, as well as estimated liquidity provider fees. + * @type {Array} + * @memberof ChainflipBaasQuoteQuote + */ + poolInfo?: Array; + /** + * The estimated time the swap will take. + * @type {number} + * @memberof ChainflipBaasQuoteQuote + */ + readonly estimatedDurationSeconds?: number; + /** + * The number of "sub-swaps" to perform for a DCA swap. + * @type {number} + * @memberof ChainflipBaasQuoteQuote + */ + chunkIntervalBlocks?: number | null; + /** + * The delay between the "sub-swaps" of a DCA swap in number of blocks. + * @type {number} + * @memberof ChainflipBaasQuoteQuote + */ + numberOfChunks?: number | null; + /** + * + * @type {ChainflipBaasQuoteBoostQuote} + * @memberof ChainflipBaasQuoteQuote + */ + boostQuote?: ChainflipBaasQuoteBoostQuote; +} + + +/** + * @export + */ +export const ChainflipBaasQuoteQuoteTypeEnum = { + Regular: 'regular', + Dca: 'dca' +} as const; +export type ChainflipBaasQuoteQuoteTypeEnum = typeof ChainflipBaasQuoteQuoteTypeEnum[keyof typeof ChainflipBaasQuoteQuoteTypeEnum]; + + +/** + * Check if a given object implements the ChainflipBaasQuoteQuote interface. + */ +export function instanceOfChainflipBaasQuoteQuote(value: object): boolean { + let isInstance = true; + + return isInstance; +} + +export function ChainflipBaasQuoteQuoteFromJSON(json: any): ChainflipBaasQuoteQuote { + return ChainflipBaasQuoteQuoteFromJSONTyped(json, false); +} + +export function ChainflipBaasQuoteQuoteFromJSONTyped(json: any, ignoreDiscriminator: boolean): ChainflipBaasQuoteQuote { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'type': !exists(json, 'type') ? undefined : json['type'], + 'ingressAsset': !exists(json, 'ingressAsset') ? undefined : json['ingressAsset'], + 'ingressAmount': !exists(json, 'ingressAmount') ? undefined : json['ingressAmount'], + 'ingressAmountNative': !exists(json, 'ingressAmountNative') ? undefined : json['ingressAmountNative'], + 'egressAsset': !exists(json, 'egressAsset') ? undefined : json['egressAsset'], + 'egressAmount': !exists(json, 'egressAmount') ? undefined : json['egressAmount'], + 'egressAmountNative': !exists(json, 'egressAmountNative') ? undefined : json['egressAmountNative'], + 'includedFees': !exists(json, 'includedFees') ? undefined : ((json['includedFees'] as Array).map(ChainflipBaasQuoteQuoteFeeFromJSON)), + 'lowLiquidityWarning': !exists(json, 'lowLiquidityWarning') ? undefined : json['lowLiquidityWarning'], + 'poolInfo': !exists(json, 'poolInfo') ? undefined : ((json['poolInfo'] as Array).map(ChainflipBaasQuotePoolInfoFromJSON)), + 'estimatedDurationSeconds': !exists(json, 'estimatedDurationSeconds') ? undefined : json['estimatedDurationSeconds'], + 'chunkIntervalBlocks': !exists(json, 'chunkIntervalBlocks') ? undefined : json['chunkIntervalBlocks'], + 'numberOfChunks': !exists(json, 'numberOfChunks') ? undefined : json['numberOfChunks'], + 'boostQuote': !exists(json, 'boostQuote') ? undefined : ChainflipBaasQuoteBoostQuoteFromJSON(json['boostQuote']), + }; +} + +export function ChainflipBaasQuoteQuoteToJSON(value?: ChainflipBaasQuoteQuote | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'ingressAsset': value.ingressAsset, + 'ingressAmount': value.ingressAmount, + 'egressAsset': value.egressAsset, + 'poolInfo': value.poolInfo === undefined ? undefined : ((value.poolInfo as Array).map(ChainflipBaasQuotePoolInfoToJSON)), + 'chunkIntervalBlocks': value.chunkIntervalBlocks, + 'numberOfChunks': value.numberOfChunks, + 'boostQuote': ChainflipBaasQuoteBoostQuoteToJSON(value.boostQuote), + }; +} + diff --git a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasQuoteQuoteFee.ts b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasQuoteQuoteFee.ts new file mode 100644 index 00000000000..754189852f6 --- /dev/null +++ b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasQuoteQuoteFee.ts @@ -0,0 +1,105 @@ +// @ts-nocheck +/* tslint:disable */ +/* eslint-disable */ +/** + * Chainflip Broker as a Service + * Run your own Chainflip Broker without any hassle. + * + * The version of the OpenAPI document: v1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +/** + * + * @export + * @interface ChainflipBaasQuoteQuoteFee + */ +export interface ChainflipBaasQuoteQuoteFee { + /** + * The type of fee. + * @type {string} + * @memberof ChainflipBaasQuoteQuoteFee + */ + type?: ChainflipBaasQuoteQuoteFeeTypeEnum; + /** + * The asset the fee is processed in. + * @type {string} + * @memberof ChainflipBaasQuoteQuoteFee + */ + asset?: string | null; + /** + * The fee amount. + * @type {number} + * @memberof ChainflipBaasQuoteQuoteFee + */ + amount?: number; + /** + * The fee amount in native units. + * @type {string} + * @memberof ChainflipBaasQuoteQuoteFee + */ + amountNative?: string; +} + + +/** + * @export + */ +export const ChainflipBaasQuoteQuoteFeeTypeEnum = { + Ingress: 'ingress', + Broker: 'broker', + Network: 'network', + Liquidity: 'liquidity', + Egress: 'egress', + Boost: 'boost' +} as const; +export type ChainflipBaasQuoteQuoteFeeTypeEnum = typeof ChainflipBaasQuoteQuoteFeeTypeEnum[keyof typeof ChainflipBaasQuoteQuoteFeeTypeEnum]; + + +/** + * Check if a given object implements the ChainflipBaasQuoteQuoteFee interface. + */ +export function instanceOfChainflipBaasQuoteQuoteFee(value: object): boolean { + let isInstance = true; + + return isInstance; +} + +export function ChainflipBaasQuoteQuoteFeeFromJSON(json: any): ChainflipBaasQuoteQuoteFee { + return ChainflipBaasQuoteQuoteFeeFromJSONTyped(json, false); +} + +export function ChainflipBaasQuoteQuoteFeeFromJSONTyped(json: any, ignoreDiscriminator: boolean): ChainflipBaasQuoteQuoteFee { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'type': !exists(json, 'type') ? undefined : json['type'], + 'asset': !exists(json, 'asset') ? undefined : json['asset'], + 'amount': !exists(json, 'amount') ? undefined : json['amount'], + 'amountNative': !exists(json, 'amountNative') ? undefined : json['amountNative'], + }; +} + +export function ChainflipBaasQuoteQuoteFeeToJSON(value?: ChainflipBaasQuoteQuoteFee | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'type': value.type, + 'asset': value.asset, + 'amount': value.amount, + 'amountNative': value.amountNative, + }; +} + diff --git a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasRpcRpcRequest.ts b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasRpcRpcRequest.ts new file mode 100644 index 00000000000..e05ed6dea0e --- /dev/null +++ b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasRpcRpcRequest.ts @@ -0,0 +1,104 @@ +// @ts-nocheck +/* tslint:disable */ +/* eslint-disable */ +/** + * Chainflip Broker as a Service + * Run your own Chainflip Broker without any hassle. + * + * The version of the OpenAPI document: v1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +/** + * + * @export + * @interface ChainflipBaasRpcRpcRequest + */ +export interface ChainflipBaasRpcRpcRequest { + /** + * Hardcode "1" + * @type {number} + * @memberof ChainflipBaasRpcRpcRequest + */ + id: number; + /** + * Hardcode "2.0" + * @type {string} + * @memberof ChainflipBaasRpcRpcRequest + */ + jsonrpc: string; + /** + * Hardcode "broker_request_swap_deposit_address" + * @type {string} + * @memberof ChainflipBaasRpcRpcRequest + */ + method: string; + /** + * source_asset: Source asset. + * + * destination_asset: Egress asset. + * + * destination_address: Egress Address. + * + * broker_commission: Will be ignored and configured partner commission will be used. + * + * channel_metadata: (Optional) Cross-chain message metadata as a JSON object: {"gas_budget": <amount>, "message":<hex_string>, "cf_parameters": <hex_string>}. Where message and cf_parameters are hex encoded strings. + * + * boost_fee: (Optional) Maximum accepted boost fee in basis points (100th of a percent). + * @type {Array} + * @memberof ChainflipBaasRpcRpcRequest + */ + params: Array; +} + +/** + * Check if a given object implements the ChainflipBaasRpcRpcRequest interface. + */ +export function instanceOfChainflipBaasRpcRpcRequest(value: object): boolean { + let isInstance = true; + isInstance = isInstance && "id" in value; + isInstance = isInstance && "jsonrpc" in value; + isInstance = isInstance && "method" in value; + isInstance = isInstance && "params" in value; + + return isInstance; +} + +export function ChainflipBaasRpcRpcRequestFromJSON(json: any): ChainflipBaasRpcRpcRequest { + return ChainflipBaasRpcRpcRequestFromJSONTyped(json, false); +} + +export function ChainflipBaasRpcRpcRequestFromJSONTyped(json: any, ignoreDiscriminator: boolean): ChainflipBaasRpcRpcRequest { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'id': json['id'], + 'jsonrpc': json['jsonrpc'], + 'method': json['method'], + 'params': json['params'], + }; +} + +export function ChainflipBaasRpcRpcRequestToJSON(value?: ChainflipBaasRpcRpcRequest | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'id': value.id, + 'jsonrpc': value.jsonrpc, + 'method': value.method, + 'params': value.params, + }; +} + diff --git a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusAffiliateBroker.ts b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusAffiliateBroker.ts new file mode 100644 index 00000000000..ef32761419a --- /dev/null +++ b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusAffiliateBroker.ts @@ -0,0 +1,72 @@ +// @ts-nocheck +/* tslint:disable */ +/* eslint-disable */ +/** + * Chainflip Broker as a Service + * Run your own Chainflip Broker without any hassle. + * + * The version of the OpenAPI document: v1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +/** + * + * @export + * @interface ChainflipBaasStatusAffiliateBroker + */ +export interface ChainflipBaasStatusAffiliateBroker { + /** + * + * @type {string} + * @memberof ChainflipBaasStatusAffiliateBroker + */ + readonly account?: string; + /** + * + * @type {number} + * @memberof ChainflipBaasStatusAffiliateBroker + */ + readonly commissionBps?: number; +} + +/** + * Check if a given object implements the ChainflipBaasStatusAffiliateBroker interface. + */ +export function instanceOfChainflipBaasStatusAffiliateBroker(value: object): boolean { + let isInstance = true; + + return isInstance; +} + +export function ChainflipBaasStatusAffiliateBrokerFromJSON(json: any): ChainflipBaasStatusAffiliateBroker { + return ChainflipBaasStatusAffiliateBrokerFromJSONTyped(json, false); +} + +export function ChainflipBaasStatusAffiliateBrokerFromJSONTyped(json: any, ignoreDiscriminator: boolean): ChainflipBaasStatusAffiliateBroker { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'account': !exists(json, 'account') ? undefined : json['account'], + 'commissionBps': !exists(json, 'commissionBps') ? undefined : json['commissionBps'], + }; +} + +export function ChainflipBaasStatusAffiliateBrokerToJSON(value?: ChainflipBaasStatusAffiliateBroker | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + }; +} + diff --git a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusBoost.ts b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusBoost.ts new file mode 100644 index 00000000000..a32ef9aad81 --- /dev/null +++ b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusBoost.ts @@ -0,0 +1,114 @@ +// @ts-nocheck +/* tslint:disable */ +/* eslint-disable */ +/** + * Chainflip Broker as a Service + * Run your own Chainflip Broker without any hassle. + * + * The version of the OpenAPI document: v1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +/** + * + * @export + * @interface ChainflipBaasStatusBoost + */ +export interface ChainflipBaasStatusBoost { + /** + * + * @type {number} + * @memberof ChainflipBaasStatusBoost + */ + readonly maximumBoostFeeBps?: number; + /** + * + * @type {number} + * @memberof ChainflipBaasStatusBoost + */ + readonly effectiveBoostFeeBps?: number | null; + /** + * + * @type {number} + * @memberof ChainflipBaasStatusBoost + */ + readonly boostedAt?: number | null; + /** + * + * @type {Date} + * @memberof ChainflipBaasStatusBoost + */ + readonly boostedAtDate?: Date | null; + /** + * + * @type {string} + * @memberof ChainflipBaasStatusBoost + */ + readonly boostedBlockIndex?: string | null; + /** + * + * @type {number} + * @memberof ChainflipBaasStatusBoost + */ + readonly skippedAt?: number | null; + /** + * + * @type {Date} + * @memberof ChainflipBaasStatusBoost + */ + readonly skippedAtDate?: Date | null; + /** + * + * @type {string} + * @memberof ChainflipBaasStatusBoost + */ + readonly skippedBlockIndex?: string | null; +} + +/** + * Check if a given object implements the ChainflipBaasStatusBoost interface. + */ +export function instanceOfChainflipBaasStatusBoost(value: object): boolean { + let isInstance = true; + + return isInstance; +} + +export function ChainflipBaasStatusBoostFromJSON(json: any): ChainflipBaasStatusBoost { + return ChainflipBaasStatusBoostFromJSONTyped(json, false); +} + +export function ChainflipBaasStatusBoostFromJSONTyped(json: any, ignoreDiscriminator: boolean): ChainflipBaasStatusBoost { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'maximumBoostFeeBps': !exists(json, 'maximumBoostFeeBps') ? undefined : json['maximumBoostFeeBps'], + 'effectiveBoostFeeBps': !exists(json, 'effectiveBoostFeeBps') ? undefined : json['effectiveBoostFeeBps'], + 'boostedAt': !exists(json, 'boostedAt') ? undefined : json['boostedAt'], + 'boostedAtDate': !exists(json, 'boostedAtDate') ? undefined : (json['boostedAtDate'] === null ? null : new Date(json['boostedAtDate'])), + 'boostedBlockIndex': !exists(json, 'boostedBlockIndex') ? undefined : json['boostedBlockIndex'], + 'skippedAt': !exists(json, 'skippedAt') ? undefined : json['skippedAt'], + 'skippedAtDate': !exists(json, 'skippedAtDate') ? undefined : (json['skippedAtDate'] === null ? null : new Date(json['skippedAtDate'])), + 'skippedBlockIndex': !exists(json, 'skippedBlockIndex') ? undefined : json['skippedBlockIndex'], + }; +} + +export function ChainflipBaasStatusBoostToJSON(value?: ChainflipBaasStatusBoost | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + }; +} + diff --git a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusCcmParameters.ts b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusCcmParameters.ts new file mode 100644 index 00000000000..d029a854f37 --- /dev/null +++ b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusCcmParameters.ts @@ -0,0 +1,79 @@ +// @ts-nocheck +/* tslint:disable */ +/* eslint-disable */ +/** + * Chainflip Broker as a Service + * Run your own Chainflip Broker without any hassle. + * + * The version of the OpenAPI document: v1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +/** + * + * @export + * @interface ChainflipBaasStatusCcmParameters + */ +export interface ChainflipBaasStatusCcmParameters { + /** + * + * @type {string} + * @memberof ChainflipBaasStatusCcmParameters + */ + readonly gasBudget?: string; + /** + * + * @type {string} + * @memberof ChainflipBaasStatusCcmParameters + */ + readonly message?: string; + /** + * + * @type {string} + * @memberof ChainflipBaasStatusCcmParameters + */ + readonly cfParameters?: string | null; +} + +/** + * Check if a given object implements the ChainflipBaasStatusCcmParameters interface. + */ +export function instanceOfChainflipBaasStatusCcmParameters(value: object): boolean { + let isInstance = true; + + return isInstance; +} + +export function ChainflipBaasStatusCcmParametersFromJSON(json: any): ChainflipBaasStatusCcmParameters { + return ChainflipBaasStatusCcmParametersFromJSONTyped(json, false); +} + +export function ChainflipBaasStatusCcmParametersFromJSONTyped(json: any, ignoreDiscriminator: boolean): ChainflipBaasStatusCcmParameters { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'gasBudget': !exists(json, 'gasBudget') ? undefined : json['gasBudget'], + 'message': !exists(json, 'message') ? undefined : json['message'], + 'cfParameters': !exists(json, 'cfParameters') ? undefined : json['cfParameters'], + }; +} + +export function ChainflipBaasStatusCcmParametersToJSON(value?: ChainflipBaasStatusCcmParameters | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + }; +} + diff --git a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusChunkInfo.ts b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusChunkInfo.ts new file mode 100644 index 00000000000..32814c5a17f --- /dev/null +++ b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusChunkInfo.ts @@ -0,0 +1,149 @@ +// @ts-nocheck +/* tslint:disable */ +/* eslint-disable */ +/** + * Chainflip Broker as a Service + * Run your own Chainflip Broker without any hassle. + * + * The version of the OpenAPI document: v1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +/** + * + * @export + * @interface ChainflipBaasStatusChunkInfo + */ +export interface ChainflipBaasStatusChunkInfo { + /** + * + * @type {string} + * @memberof ChainflipBaasStatusChunkInfo + */ + readonly inputAmountNative?: string; + /** + * + * @type {number} + * @memberof ChainflipBaasStatusChunkInfo + */ + readonly inputAmount?: number; + /** + * + * @type {string} + * @memberof ChainflipBaasStatusChunkInfo + */ + readonly intermediateAmountNative?: string | null; + /** + * + * @type {number} + * @memberof ChainflipBaasStatusChunkInfo + */ + readonly intermediateAmount?: number | null; + /** + * + * @type {string} + * @memberof ChainflipBaasStatusChunkInfo + */ + readonly outputAmountNative?: string | null; + /** + * + * @type {number} + * @memberof ChainflipBaasStatusChunkInfo + */ + readonly outputAmount?: number | null; + /** + * + * @type {number} + * @memberof ChainflipBaasStatusChunkInfo + */ + readonly scheduledAt?: number; + /** + * + * @type {Date} + * @memberof ChainflipBaasStatusChunkInfo + */ + readonly scheduledAtDate?: Date; + /** + * + * @type {string} + * @memberof ChainflipBaasStatusChunkInfo + */ + readonly scheduledBlockIndex?: string; + /** + * + * @type {number} + * @memberof ChainflipBaasStatusChunkInfo + */ + readonly executedAt?: number | null; + /** + * + * @type {Date} + * @memberof ChainflipBaasStatusChunkInfo + */ + readonly executedAtDate?: Date | null; + /** + * + * @type {string} + * @memberof ChainflipBaasStatusChunkInfo + */ + readonly executedBlockIndex?: string | null; + /** + * + * @type {number} + * @memberof ChainflipBaasStatusChunkInfo + */ + readonly retryCount?: number; +} + +/** + * Check if a given object implements the ChainflipBaasStatusChunkInfo interface. + */ +export function instanceOfChainflipBaasStatusChunkInfo(value: object): boolean { + let isInstance = true; + + return isInstance; +} + +export function ChainflipBaasStatusChunkInfoFromJSON(json: any): ChainflipBaasStatusChunkInfo { + return ChainflipBaasStatusChunkInfoFromJSONTyped(json, false); +} + +export function ChainflipBaasStatusChunkInfoFromJSONTyped(json: any, ignoreDiscriminator: boolean): ChainflipBaasStatusChunkInfo { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'inputAmountNative': !exists(json, 'inputAmountNative') ? undefined : json['inputAmountNative'], + 'inputAmount': !exists(json, 'inputAmount') ? undefined : json['inputAmount'], + 'intermediateAmountNative': !exists(json, 'intermediateAmountNative') ? undefined : json['intermediateAmountNative'], + 'intermediateAmount': !exists(json, 'intermediateAmount') ? undefined : json['intermediateAmount'], + 'outputAmountNative': !exists(json, 'outputAmountNative') ? undefined : json['outputAmountNative'], + 'outputAmount': !exists(json, 'outputAmount') ? undefined : json['outputAmount'], + 'scheduledAt': !exists(json, 'scheduledAt') ? undefined : json['scheduledAt'], + 'scheduledAtDate': !exists(json, 'scheduledAtDate') ? undefined : (new Date(json['scheduledAtDate'])), + 'scheduledBlockIndex': !exists(json, 'scheduledBlockIndex') ? undefined : json['scheduledBlockIndex'], + 'executedAt': !exists(json, 'executedAt') ? undefined : json['executedAt'], + 'executedAtDate': !exists(json, 'executedAtDate') ? undefined : (json['executedAtDate'] === null ? null : new Date(json['executedAtDate'])), + 'executedBlockIndex': !exists(json, 'executedBlockIndex') ? undefined : json['executedBlockIndex'], + 'retryCount': !exists(json, 'retryCount') ? undefined : json['retryCount'], + }; +} + +export function ChainflipBaasStatusChunkInfoToJSON(value?: ChainflipBaasStatusChunkInfo | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + }; +} + diff --git a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusDca.ts b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusDca.ts new file mode 100644 index 00000000000..0f261b0950c --- /dev/null +++ b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusDca.ts @@ -0,0 +1,95 @@ +// @ts-nocheck +/* tslint:disable */ +/* eslint-disable */ +/** + * Chainflip Broker as a Service + * Run your own Chainflip Broker without any hassle. + * + * The version of the OpenAPI document: v1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +import type { ChainflipBaasStatusChunkInfo } from './ChainflipBaasStatusChunkInfo'; +import { + ChainflipBaasStatusChunkInfoFromJSON, + ChainflipBaasStatusChunkInfoFromJSONTyped, + ChainflipBaasStatusChunkInfoToJSON, +} from './ChainflipBaasStatusChunkInfo'; + +/** + * + * @export + * @interface ChainflipBaasStatusDca + */ +export interface ChainflipBaasStatusDca { + /** + * + * @type {ChainflipBaasStatusChunkInfo} + * @memberof ChainflipBaasStatusDca + */ + lastExecutedChunk?: ChainflipBaasStatusChunkInfo; + /** + * + * @type {ChainflipBaasStatusChunkInfo} + * @memberof ChainflipBaasStatusDca + */ + currentChunk?: ChainflipBaasStatusChunkInfo; + /** + * + * @type {number} + * @memberof ChainflipBaasStatusDca + */ + readonly executedChunks?: number; + /** + * + * @type {number} + * @memberof ChainflipBaasStatusDca + */ + readonly remainingChunks?: number; +} + +/** + * Check if a given object implements the ChainflipBaasStatusDca interface. + */ +export function instanceOfChainflipBaasStatusDca(value: object): boolean { + let isInstance = true; + + return isInstance; +} + +export function ChainflipBaasStatusDcaFromJSON(json: any): ChainflipBaasStatusDca { + return ChainflipBaasStatusDcaFromJSONTyped(json, false); +} + +export function ChainflipBaasStatusDcaFromJSONTyped(json: any, ignoreDiscriminator: boolean): ChainflipBaasStatusDca { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'lastExecutedChunk': !exists(json, 'lastExecutedChunk') ? undefined : ChainflipBaasStatusChunkInfoFromJSON(json['lastExecutedChunk']), + 'currentChunk': !exists(json, 'currentChunk') ? undefined : ChainflipBaasStatusChunkInfoFromJSON(json['currentChunk']), + 'executedChunks': !exists(json, 'executedChunks') ? undefined : json['executedChunks'], + 'remainingChunks': !exists(json, 'remainingChunks') ? undefined : json['remainingChunks'], + }; +} + +export function ChainflipBaasStatusDcaToJSON(value?: ChainflipBaasStatusDca | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'lastExecutedChunk': ChainflipBaasStatusChunkInfoToJSON(value.lastExecutedChunk), + 'currentChunk': ChainflipBaasStatusChunkInfoToJSON(value.currentChunk), + }; +} + diff --git a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusDcaParameters.ts b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusDcaParameters.ts new file mode 100644 index 00000000000..f08cedee1a5 --- /dev/null +++ b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusDcaParameters.ts @@ -0,0 +1,72 @@ +// @ts-nocheck +/* tslint:disable */ +/* eslint-disable */ +/** + * Chainflip Broker as a Service + * Run your own Chainflip Broker without any hassle. + * + * The version of the OpenAPI document: v1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +/** + * + * @export + * @interface ChainflipBaasStatusDcaParameters + */ +export interface ChainflipBaasStatusDcaParameters { + /** + * + * @type {number} + * @memberof ChainflipBaasStatusDcaParameters + */ + readonly numberOfChunks?: number; + /** + * + * @type {number} + * @memberof ChainflipBaasStatusDcaParameters + */ + readonly chunkIntervalBlocks?: number; +} + +/** + * Check if a given object implements the ChainflipBaasStatusDcaParameters interface. + */ +export function instanceOfChainflipBaasStatusDcaParameters(value: object): boolean { + let isInstance = true; + + return isInstance; +} + +export function ChainflipBaasStatusDcaParametersFromJSON(json: any): ChainflipBaasStatusDcaParameters { + return ChainflipBaasStatusDcaParametersFromJSONTyped(json, false); +} + +export function ChainflipBaasStatusDcaParametersFromJSONTyped(json: any, ignoreDiscriminator: boolean): ChainflipBaasStatusDcaParameters { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'numberOfChunks': !exists(json, 'numberOfChunks') ? undefined : json['numberOfChunks'], + 'chunkIntervalBlocks': !exists(json, 'chunkIntervalBlocks') ? undefined : json['chunkIntervalBlocks'], + }; +} + +export function ChainflipBaasStatusDcaParametersToJSON(value?: ChainflipBaasStatusDcaParameters | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + }; +} + diff --git a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusDeposit.ts b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusDeposit.ts new file mode 100644 index 00000000000..f618fb53344 --- /dev/null +++ b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusDeposit.ts @@ -0,0 +1,143 @@ +// @ts-nocheck +/* tslint:disable */ +/* eslint-disable */ +/** + * Chainflip Broker as a Service + * Run your own Chainflip Broker without any hassle. + * + * The version of the OpenAPI document: v1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +import type { ChainflipBaasStatusFailure } from './ChainflipBaasStatusFailure'; +import { + ChainflipBaasStatusFailureFromJSON, + ChainflipBaasStatusFailureFromJSONTyped, + ChainflipBaasStatusFailureToJSON, +} from './ChainflipBaasStatusFailure'; + +/** + * + * @export + * @interface ChainflipBaasStatusDeposit + */ +export interface ChainflipBaasStatusDeposit { + /** + * + * @type {string} + * @memberof ChainflipBaasStatusDeposit + */ + readonly amountNative?: string; + /** + * + * @type {number} + * @memberof ChainflipBaasStatusDeposit + */ + readonly amount?: number; + /** + * + * @type {string} + * @memberof ChainflipBaasStatusDeposit + */ + readonly transactionReference?: string | null; + /** + * + * @type {number} + * @memberof ChainflipBaasStatusDeposit + */ + readonly transactionConfirmations?: number | null; + /** + * + * @type {number} + * @memberof ChainflipBaasStatusDeposit + */ + readonly witnessedAt?: number | null; + /** + * + * @type {Date} + * @memberof ChainflipBaasStatusDeposit + */ + readonly witnessedAtDate?: Date | null; + /** + * + * @type {string} + * @memberof ChainflipBaasStatusDeposit + */ + readonly witnessedBlockIndex?: string | null; + /** + * + * @type {ChainflipBaasStatusFailure} + * @memberof ChainflipBaasStatusDeposit + */ + failure?: ChainflipBaasStatusFailure; + /** + * + * @type {number} + * @memberof ChainflipBaasStatusDeposit + */ + readonly failedAt?: number | null; + /** + * + * @type {Date} + * @memberof ChainflipBaasStatusDeposit + */ + readonly failedAtDate?: Date | null; + /** + * + * @type {string} + * @memberof ChainflipBaasStatusDeposit + */ + readonly failedBlockIndex?: string | null; +} + +/** + * Check if a given object implements the ChainflipBaasStatusDeposit interface. + */ +export function instanceOfChainflipBaasStatusDeposit(value: object): boolean { + let isInstance = true; + + return isInstance; +} + +export function ChainflipBaasStatusDepositFromJSON(json: any): ChainflipBaasStatusDeposit { + return ChainflipBaasStatusDepositFromJSONTyped(json, false); +} + +export function ChainflipBaasStatusDepositFromJSONTyped(json: any, ignoreDiscriminator: boolean): ChainflipBaasStatusDeposit { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'amountNative': !exists(json, 'amountNative') ? undefined : json['amountNative'], + 'amount': !exists(json, 'amount') ? undefined : json['amount'], + 'transactionReference': !exists(json, 'transactionReference') ? undefined : json['transactionReference'], + 'transactionConfirmations': !exists(json, 'transactionConfirmations') ? undefined : json['transactionConfirmations'], + 'witnessedAt': !exists(json, 'witnessedAt') ? undefined : json['witnessedAt'], + 'witnessedAtDate': !exists(json, 'witnessedAtDate') ? undefined : (json['witnessedAtDate'] === null ? null : new Date(json['witnessedAtDate'])), + 'witnessedBlockIndex': !exists(json, 'witnessedBlockIndex') ? undefined : json['witnessedBlockIndex'], + 'failure': !exists(json, 'failure') ? undefined : ChainflipBaasStatusFailureFromJSON(json['failure']), + 'failedAt': !exists(json, 'failedAt') ? undefined : json['failedAt'], + 'failedAtDate': !exists(json, 'failedAtDate') ? undefined : (json['failedAtDate'] === null ? null : new Date(json['failedAtDate'])), + 'failedBlockIndex': !exists(json, 'failedBlockIndex') ? undefined : json['failedBlockIndex'], + }; +} + +export function ChainflipBaasStatusDepositToJSON(value?: ChainflipBaasStatusDeposit | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'failure': ChainflipBaasStatusFailureToJSON(value.failure), + }; +} + diff --git a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusDepositChannel.ts b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusDepositChannel.ts new file mode 100644 index 00000000000..7be58f17604 --- /dev/null +++ b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusDepositChannel.ts @@ -0,0 +1,184 @@ +// @ts-nocheck +/* tslint:disable */ +/* eslint-disable */ +/** + * Chainflip Broker as a Service + * Run your own Chainflip Broker without any hassle. + * + * The version of the OpenAPI document: v1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +import type { ChainflipBaasStatusAffiliateBroker } from './ChainflipBaasStatusAffiliateBroker'; +import { + ChainflipBaasStatusAffiliateBrokerFromJSON, + ChainflipBaasStatusAffiliateBrokerFromJSONTyped, + ChainflipBaasStatusAffiliateBrokerToJSON, +} from './ChainflipBaasStatusAffiliateBroker'; +import type { ChainflipBaasStatusDcaParameters } from './ChainflipBaasStatusDcaParameters'; +import { + ChainflipBaasStatusDcaParametersFromJSON, + ChainflipBaasStatusDcaParametersFromJSONTyped, + ChainflipBaasStatusDcaParametersToJSON, +} from './ChainflipBaasStatusDcaParameters'; +import type { ChainflipBaasStatusFillOrKillParameters } from './ChainflipBaasStatusFillOrKillParameters'; +import { + ChainflipBaasStatusFillOrKillParametersFromJSON, + ChainflipBaasStatusFillOrKillParametersFromJSONTyped, + ChainflipBaasStatusFillOrKillParametersToJSON, +} from './ChainflipBaasStatusFillOrKillParameters'; + +/** + * + * @export + * @interface ChainflipBaasStatusDepositChannel + */ +export interface ChainflipBaasStatusDepositChannel { + /** + * + * @type {string} + * @memberof ChainflipBaasStatusDepositChannel + */ + readonly id?: string; + /** + * + * @type {number} + * @memberof ChainflipBaasStatusDepositChannel + */ + readonly createdAt?: number; + /** + * + * @type {Date} + * @memberof ChainflipBaasStatusDepositChannel + */ + readonly createdAtDate?: Date; + /** + * + * @type {number} + * @memberof ChainflipBaasStatusDepositChannel + */ + readonly brokerCommissionBps?: number; + /** + * + * @type {string} + * @memberof ChainflipBaasStatusDepositChannel + */ + readonly depositAddress?: string; + /** + * + * @type {string} + * @memberof ChainflipBaasStatusDepositChannel + */ + readonly sourceChainExpiryBlock?: string; + /** + * + * @type {number} + * @memberof ChainflipBaasStatusDepositChannel + */ + readonly estimatedExpiryTime?: number; + /** + * + * @type {Date} + * @memberof ChainflipBaasStatusDepositChannel + */ + readonly estimatedExpiryDate?: Date; + /** + * + * @type {number} + * @memberof ChainflipBaasStatusDepositChannel + */ + readonly expectedDepositAmount?: number | null; + /** + * + * @type {string} + * @memberof ChainflipBaasStatusDepositChannel + */ + readonly expectedDepositAmountNative?: string | null; + /** + * + * @type {boolean} + * @memberof ChainflipBaasStatusDepositChannel + */ + readonly isExpired?: boolean; + /** + * + * @type {boolean} + * @memberof ChainflipBaasStatusDepositChannel + */ + readonly openedThroughBackend?: boolean; + /** + * + * @type {Array} + * @memberof ChainflipBaasStatusDepositChannel + */ + readonly affiliateBrokers?: Array | null; + /** + * + * @type {ChainflipBaasStatusFillOrKillParameters} + * @memberof ChainflipBaasStatusDepositChannel + */ + fillOrKillParams?: ChainflipBaasStatusFillOrKillParameters; + /** + * + * @type {ChainflipBaasStatusDcaParameters} + * @memberof ChainflipBaasStatusDepositChannel + */ + dcaParams?: ChainflipBaasStatusDcaParameters; +} + +/** + * Check if a given object implements the ChainflipBaasStatusDepositChannel interface. + */ +export function instanceOfChainflipBaasStatusDepositChannel(value: object): boolean { + let isInstance = true; + + return isInstance; +} + +export function ChainflipBaasStatusDepositChannelFromJSON(json: any): ChainflipBaasStatusDepositChannel { + return ChainflipBaasStatusDepositChannelFromJSONTyped(json, false); +} + +export function ChainflipBaasStatusDepositChannelFromJSONTyped(json: any, ignoreDiscriminator: boolean): ChainflipBaasStatusDepositChannel { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'id': !exists(json, 'id') ? undefined : json['id'], + 'createdAt': !exists(json, 'createdAt') ? undefined : json['createdAt'], + 'createdAtDate': !exists(json, 'createdAtDate') ? undefined : (new Date(json['createdAtDate'])), + 'brokerCommissionBps': !exists(json, 'brokerCommissionBps') ? undefined : json['brokerCommissionBps'], + 'depositAddress': !exists(json, 'depositAddress') ? undefined : json['depositAddress'], + 'sourceChainExpiryBlock': !exists(json, 'sourceChainExpiryBlock') ? undefined : json['sourceChainExpiryBlock'], + 'estimatedExpiryTime': !exists(json, 'estimatedExpiryTime') ? undefined : json['estimatedExpiryTime'], + 'estimatedExpiryDate': !exists(json, 'estimatedExpiryDate') ? undefined : (new Date(json['estimatedExpiryDate'])), + 'expectedDepositAmount': !exists(json, 'expectedDepositAmount') ? undefined : json['expectedDepositAmount'], + 'expectedDepositAmountNative': !exists(json, 'expectedDepositAmountNative') ? undefined : json['expectedDepositAmountNative'], + 'isExpired': !exists(json, 'isExpired') ? undefined : json['isExpired'], + 'openedThroughBackend': !exists(json, 'openedThroughBackend') ? undefined : json['openedThroughBackend'], + 'affiliateBrokers': !exists(json, 'affiliateBrokers') ? undefined : (json['affiliateBrokers'] === null ? null : (json['affiliateBrokers'] as Array).map(ChainflipBaasStatusAffiliateBrokerFromJSON)), + 'fillOrKillParams': !exists(json, 'fillOrKillParams') ? undefined : ChainflipBaasStatusFillOrKillParametersFromJSON(json['fillOrKillParams']), + 'dcaParams': !exists(json, 'dcaParams') ? undefined : ChainflipBaasStatusDcaParametersFromJSON(json['dcaParams']), + }; +} + +export function ChainflipBaasStatusDepositChannelToJSON(value?: ChainflipBaasStatusDepositChannel | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'fillOrKillParams': ChainflipBaasStatusFillOrKillParametersToJSON(value.fillOrKillParams), + 'dcaParams': ChainflipBaasStatusDcaParametersToJSON(value.dcaParams), + }; +} + diff --git a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusEgress.ts b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusEgress.ts new file mode 100644 index 00000000000..ab56435015d --- /dev/null +++ b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusEgress.ts @@ -0,0 +1,150 @@ +// @ts-nocheck +/* tslint:disable */ +/* eslint-disable */ +/** + * Chainflip Broker as a Service + * Run your own Chainflip Broker without any hassle. + * + * The version of the OpenAPI document: v1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +import type { ChainflipBaasStatusFailure } from './ChainflipBaasStatusFailure'; +import { + ChainflipBaasStatusFailureFromJSON, + ChainflipBaasStatusFailureFromJSONTyped, + ChainflipBaasStatusFailureToJSON, +} from './ChainflipBaasStatusFailure'; + +/** + * + * @export + * @interface ChainflipBaasStatusEgress + */ +export interface ChainflipBaasStatusEgress { + /** + * + * @type {string} + * @memberof ChainflipBaasStatusEgress + */ + readonly amountNative?: string; + /** + * + * @type {number} + * @memberof ChainflipBaasStatusEgress + */ + readonly amount?: number; + /** + * + * @type {number} + * @memberof ChainflipBaasStatusEgress + */ + readonly scheduledAt?: number | null; + /** + * + * @type {Date} + * @memberof ChainflipBaasStatusEgress + */ + readonly scheduledAtDate?: Date | null; + /** + * + * @type {string} + * @memberof ChainflipBaasStatusEgress + */ + readonly scheduledBlockIndex?: string | null; + /** + * + * @type {string} + * @memberof ChainflipBaasStatusEgress + */ + readonly transactionReference?: string | null; + /** + * + * @type {number} + * @memberof ChainflipBaasStatusEgress + */ + readonly witnessedAt?: number | null; + /** + * + * @type {string} + * @memberof ChainflipBaasStatusEgress + */ + readonly witnessedBlockIndex?: string | null; + /** + * + * @type {ChainflipBaasStatusFailure} + * @memberof ChainflipBaasStatusEgress + */ + failure?: ChainflipBaasStatusFailure; + /** + * + * @type {number} + * @memberof ChainflipBaasStatusEgress + */ + readonly failedAt?: number | null; + /** + * + * @type {Date} + * @memberof ChainflipBaasStatusEgress + */ + readonly failedAtDate?: Date | null; + /** + * + * @type {string} + * @memberof ChainflipBaasStatusEgress + */ + readonly failedBlockIndex?: string | null; +} + +/** + * Check if a given object implements the ChainflipBaasStatusEgress interface. + */ +export function instanceOfChainflipBaasStatusEgress(value: object): boolean { + let isInstance = true; + + return isInstance; +} + +export function ChainflipBaasStatusEgressFromJSON(json: any): ChainflipBaasStatusEgress { + return ChainflipBaasStatusEgressFromJSONTyped(json, false); +} + +export function ChainflipBaasStatusEgressFromJSONTyped(json: any, ignoreDiscriminator: boolean): ChainflipBaasStatusEgress { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'amountNative': !exists(json, 'amountNative') ? undefined : json['amountNative'], + 'amount': !exists(json, 'amount') ? undefined : json['amount'], + 'scheduledAt': !exists(json, 'scheduledAt') ? undefined : json['scheduledAt'], + 'scheduledAtDate': !exists(json, 'scheduledAtDate') ? undefined : (json['scheduledAtDate'] === null ? null : new Date(json['scheduledAtDate'])), + 'scheduledBlockIndex': !exists(json, 'scheduledBlockIndex') ? undefined : json['scheduledBlockIndex'], + 'transactionReference': !exists(json, 'transactionReference') ? undefined : json['transactionReference'], + 'witnessedAt': !exists(json, 'witnessedAt') ? undefined : json['witnessedAt'], + 'witnessedBlockIndex': !exists(json, 'witnessedBlockIndex') ? undefined : json['witnessedBlockIndex'], + 'failure': !exists(json, 'failure') ? undefined : ChainflipBaasStatusFailureFromJSON(json['failure']), + 'failedAt': !exists(json, 'failedAt') ? undefined : json['failedAt'], + 'failedAtDate': !exists(json, 'failedAtDate') ? undefined : (json['failedAtDate'] === null ? null : new Date(json['failedAtDate'])), + 'failedBlockIndex': !exists(json, 'failedBlockIndex') ? undefined : json['failedBlockIndex'], + }; +} + +export function ChainflipBaasStatusEgressToJSON(value?: ChainflipBaasStatusEgress | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'failure': ChainflipBaasStatusFailureToJSON(value.failure), + }; +} + diff --git a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusFailure.ts b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusFailure.ts new file mode 100644 index 00000000000..1f2466d474e --- /dev/null +++ b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusFailure.ts @@ -0,0 +1,101 @@ +// @ts-nocheck +/* tslint:disable */ +/* eslint-disable */ +/** + * Chainflip Broker as a Service + * Run your own Chainflip Broker without any hassle. + * + * The version of the OpenAPI document: v1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +import type { ChainflipBaasStatusReason } from './ChainflipBaasStatusReason'; +import { + ChainflipBaasStatusReasonFromJSON, + ChainflipBaasStatusReasonFromJSONTyped, + ChainflipBaasStatusReasonToJSON, +} from './ChainflipBaasStatusReason'; + +/** + * + * @export + * @interface ChainflipBaasStatusFailure + */ +export interface ChainflipBaasStatusFailure { + /** + * + * @type {number} + * @memberof ChainflipBaasStatusFailure + */ + readonly failedAt?: number; + /** + * + * @type {Date} + * @memberof ChainflipBaasStatusFailure + */ + readonly failedAtDate?: Date; + /** + * + * @type {string} + * @memberof ChainflipBaasStatusFailure + */ + readonly failedBlockIndex?: string; + /** + * + * @type {string} + * @memberof ChainflipBaasStatusFailure + */ + readonly mode?: string; + /** + * + * @type {ChainflipBaasStatusReason} + * @memberof ChainflipBaasStatusFailure + */ + reason?: ChainflipBaasStatusReason; +} + +/** + * Check if a given object implements the ChainflipBaasStatusFailure interface. + */ +export function instanceOfChainflipBaasStatusFailure(value: object): boolean { + let isInstance = true; + + return isInstance; +} + +export function ChainflipBaasStatusFailureFromJSON(json: any): ChainflipBaasStatusFailure { + return ChainflipBaasStatusFailureFromJSONTyped(json, false); +} + +export function ChainflipBaasStatusFailureFromJSONTyped(json: any, ignoreDiscriminator: boolean): ChainflipBaasStatusFailure { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'failedAt': !exists(json, 'failedAt') ? undefined : json['failedAt'], + 'failedAtDate': !exists(json, 'failedAtDate') ? undefined : (new Date(json['failedAtDate'])), + 'failedBlockIndex': !exists(json, 'failedBlockIndex') ? undefined : json['failedBlockIndex'], + 'mode': !exists(json, 'mode') ? undefined : json['mode'], + 'reason': !exists(json, 'reason') ? undefined : ChainflipBaasStatusReasonFromJSON(json['reason']), + }; +} + +export function ChainflipBaasStatusFailureToJSON(value?: ChainflipBaasStatusFailure | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'reason': ChainflipBaasStatusReasonToJSON(value.reason), + }; +} + diff --git a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusFillOrKillParameters.ts b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusFillOrKillParameters.ts new file mode 100644 index 00000000000..37c8ed3eee7 --- /dev/null +++ b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusFillOrKillParameters.ts @@ -0,0 +1,79 @@ +// @ts-nocheck +/* tslint:disable */ +/* eslint-disable */ +/** + * Chainflip Broker as a Service + * Run your own Chainflip Broker without any hassle. + * + * The version of the OpenAPI document: v1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +/** + * + * @export + * @interface ChainflipBaasStatusFillOrKillParameters + */ +export interface ChainflipBaasStatusFillOrKillParameters { + /** + * + * @type {number} + * @memberof ChainflipBaasStatusFillOrKillParameters + */ + readonly retryDurationBlocks?: number; + /** + * + * @type {string} + * @memberof ChainflipBaasStatusFillOrKillParameters + */ + readonly refundAddress?: string; + /** + * + * @type {string} + * @memberof ChainflipBaasStatusFillOrKillParameters + */ + readonly minimumPrice?: string; +} + +/** + * Check if a given object implements the ChainflipBaasStatusFillOrKillParameters interface. + */ +export function instanceOfChainflipBaasStatusFillOrKillParameters(value: object): boolean { + let isInstance = true; + + return isInstance; +} + +export function ChainflipBaasStatusFillOrKillParametersFromJSON(json: any): ChainflipBaasStatusFillOrKillParameters { + return ChainflipBaasStatusFillOrKillParametersFromJSONTyped(json, false); +} + +export function ChainflipBaasStatusFillOrKillParametersFromJSONTyped(json: any, ignoreDiscriminator: boolean): ChainflipBaasStatusFillOrKillParameters { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'retryDurationBlocks': !exists(json, 'retryDurationBlocks') ? undefined : json['retryDurationBlocks'], + 'refundAddress': !exists(json, 'refundAddress') ? undefined : json['refundAddress'], + 'minimumPrice': !exists(json, 'minimumPrice') ? undefined : json['minimumPrice'], + }; +} + +export function ChainflipBaasStatusFillOrKillParametersToJSON(value?: ChainflipBaasStatusFillOrKillParameters | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + }; +} + diff --git a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusPaidFee.ts b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusPaidFee.ts new file mode 100644 index 00000000000..b37935c3d3e --- /dev/null +++ b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusPaidFee.ts @@ -0,0 +1,101 @@ +// @ts-nocheck +/* tslint:disable */ +/* eslint-disable */ +/** + * Chainflip Broker as a Service + * Run your own Chainflip Broker without any hassle. + * + * The version of the OpenAPI document: v1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +/** + * + * @export + * @interface ChainflipBaasStatusPaidFee + */ +export interface ChainflipBaasStatusPaidFee { + /** + * + * @type {string} + * @memberof ChainflipBaasStatusPaidFee + */ + readonly type?: ChainflipBaasStatusPaidFeeTypeEnum; + /** + * + * @type {string} + * @memberof ChainflipBaasStatusPaidFee + */ + readonly asset?: string; + /** + * + * @type {string} + * @memberof ChainflipBaasStatusPaidFee + */ + readonly amountNative?: string; + /** + * + * @type {number} + * @memberof ChainflipBaasStatusPaidFee + */ + readonly amount?: number; +} + + +/** + * @export + */ +export const ChainflipBaasStatusPaidFeeTypeEnum = { + Network: 'network', + Ingress: 'ingress', + Egress: 'egress', + Broker: 'broker', + Boost: 'boost', + Liquidity: 'liquidity' +} as const; +export type ChainflipBaasStatusPaidFeeTypeEnum = typeof ChainflipBaasStatusPaidFeeTypeEnum[keyof typeof ChainflipBaasStatusPaidFeeTypeEnum]; + + +/** + * Check if a given object implements the ChainflipBaasStatusPaidFee interface. + */ +export function instanceOfChainflipBaasStatusPaidFee(value: object): boolean { + let isInstance = true; + + return isInstance; +} + +export function ChainflipBaasStatusPaidFeeFromJSON(json: any): ChainflipBaasStatusPaidFee { + return ChainflipBaasStatusPaidFeeFromJSONTyped(json, false); +} + +export function ChainflipBaasStatusPaidFeeFromJSONTyped(json: any, ignoreDiscriminator: boolean): ChainflipBaasStatusPaidFee { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'type': !exists(json, 'type') ? undefined : json['type'], + 'asset': !exists(json, 'asset') ? undefined : json['asset'], + 'amountNative': !exists(json, 'amountNative') ? undefined : json['amountNative'], + 'amount': !exists(json, 'amount') ? undefined : json['amount'], + }; +} + +export function ChainflipBaasStatusPaidFeeToJSON(value?: ChainflipBaasStatusPaidFee | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + }; +} + diff --git a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusReason.ts b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusReason.ts new file mode 100644 index 00000000000..9c9eec84fcd --- /dev/null +++ b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusReason.ts @@ -0,0 +1,72 @@ +// @ts-nocheck +/* tslint:disable */ +/* eslint-disable */ +/** + * Chainflip Broker as a Service + * Run your own Chainflip Broker without any hassle. + * + * The version of the OpenAPI document: v1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +/** + * + * @export + * @interface ChainflipBaasStatusReason + */ +export interface ChainflipBaasStatusReason { + /** + * + * @type {string} + * @memberof ChainflipBaasStatusReason + */ + readonly code?: string; + /** + * + * @type {string} + * @memberof ChainflipBaasStatusReason + */ + readonly message?: string; +} + +/** + * Check if a given object implements the ChainflipBaasStatusReason interface. + */ +export function instanceOfChainflipBaasStatusReason(value: object): boolean { + let isInstance = true; + + return isInstance; +} + +export function ChainflipBaasStatusReasonFromJSON(json: any): ChainflipBaasStatusReason { + return ChainflipBaasStatusReasonFromJSONTyped(json, false); +} + +export function ChainflipBaasStatusReasonFromJSONTyped(json: any, ignoreDiscriminator: boolean): ChainflipBaasStatusReason { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'code': !exists(json, 'code') ? undefined : json['code'], + 'message': !exists(json, 'message') ? undefined : json['message'], + }; +} + +export function ChainflipBaasStatusReasonToJSON(value?: ChainflipBaasStatusReason | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + }; +} + diff --git a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusStatusResponse.ts b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusStatusResponse.ts new file mode 100644 index 00000000000..56004260684 --- /dev/null +++ b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusStatusResponse.ts @@ -0,0 +1,81 @@ +// @ts-nocheck +/* tslint:disable */ +/* eslint-disable */ +/** + * Chainflip Broker as a Service + * Run your own Chainflip Broker without any hassle. + * + * The version of the OpenAPI document: v1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +import type { ChainflipBaasStatusSwapStatus } from './ChainflipBaasStatusSwapStatus'; +import { + ChainflipBaasStatusSwapStatusFromJSON, + ChainflipBaasStatusSwapStatusFromJSONTyped, + ChainflipBaasStatusSwapStatusToJSON, +} from './ChainflipBaasStatusSwapStatus'; + +/** + * + * @export + * @interface ChainflipBaasStatusStatusResponse + */ +export interface ChainflipBaasStatusStatusResponse { + /** + * + * @type {number} + * @memberof ChainflipBaasStatusStatusResponse + */ + id?: number; + /** + * + * @type {ChainflipBaasStatusSwapStatus} + * @memberof ChainflipBaasStatusStatusResponse + */ + status?: ChainflipBaasStatusSwapStatus; +} + +/** + * Check if a given object implements the ChainflipBaasStatusStatusResponse interface. + */ +export function instanceOfChainflipBaasStatusStatusResponse(value: object): boolean { + let isInstance = true; + + return isInstance; +} + +export function ChainflipBaasStatusStatusResponseFromJSON(json: any): ChainflipBaasStatusStatusResponse { + return ChainflipBaasStatusStatusResponseFromJSONTyped(json, false); +} + +export function ChainflipBaasStatusStatusResponseFromJSONTyped(json: any, ignoreDiscriminator: boolean): ChainflipBaasStatusStatusResponse { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'id': !exists(json, 'id') ? undefined : json['id'], + 'status': !exists(json, 'status') ? undefined : ChainflipBaasStatusSwapStatusFromJSON(json['status']), + }; +} + +export function ChainflipBaasStatusStatusResponseToJSON(value?: ChainflipBaasStatusStatusResponse | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'id': value.id, + 'status': ChainflipBaasStatusSwapStatusToJSON(value.status), + }; +} + diff --git a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusSwap.ts b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusSwap.ts new file mode 100644 index 00000000000..45482daaaf7 --- /dev/null +++ b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusSwap.ts @@ -0,0 +1,167 @@ +// @ts-nocheck +/* tslint:disable */ +/* eslint-disable */ +/** + * Chainflip Broker as a Service + * Run your own Chainflip Broker without any hassle. + * + * The version of the OpenAPI document: v1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +import type { ChainflipBaasStatusChunkInfo } from './ChainflipBaasStatusChunkInfo'; +import { + ChainflipBaasStatusChunkInfoFromJSON, + ChainflipBaasStatusChunkInfoFromJSONTyped, + ChainflipBaasStatusChunkInfoToJSON, +} from './ChainflipBaasStatusChunkInfo'; +import type { ChainflipBaasStatusDca } from './ChainflipBaasStatusDca'; +import { + ChainflipBaasStatusDcaFromJSON, + ChainflipBaasStatusDcaFromJSONTyped, + ChainflipBaasStatusDcaToJSON, +} from './ChainflipBaasStatusDca'; + +/** + * + * @export + * @interface ChainflipBaasStatusSwap + */ +export interface ChainflipBaasStatusSwap { + /** + * + * @type {string} + * @memberof ChainflipBaasStatusSwap + */ + originalInputAmountNative?: string; + /** + * + * @type {number} + * @memberof ChainflipBaasStatusSwap + */ + originalInputAmount?: number; + /** + * + * @type {string} + * @memberof ChainflipBaasStatusSwap + */ + remainingInputAmountNative?: string; + /** + * + * @type {number} + * @memberof ChainflipBaasStatusSwap + */ + remainingInputAmount?: number; + /** + * + * @type {string} + * @memberof ChainflipBaasStatusSwap + */ + swappedInputAmountNative?: string; + /** + * + * @type {number} + * @memberof ChainflipBaasStatusSwap + */ + swappedInputAmount?: number; + /** + * + * @type {string} + * @memberof ChainflipBaasStatusSwap + */ + swappedIntermediateAmountNative?: string; + /** + * + * @type {number} + * @memberof ChainflipBaasStatusSwap + */ + swappedIntermediateAmount?: number; + /** + * + * @type {string} + * @memberof ChainflipBaasStatusSwap + */ + swappedOutputAmountNative?: string; + /** + * + * @type {number} + * @memberof ChainflipBaasStatusSwap + */ + swappedOutputAmount?: number; + /** + * + * @type {ChainflipBaasStatusChunkInfo} + * @memberof ChainflipBaasStatusSwap + */ + regular?: ChainflipBaasStatusChunkInfo; + /** + * + * @type {ChainflipBaasStatusDca} + * @memberof ChainflipBaasStatusSwap + */ + dca?: ChainflipBaasStatusDca; +} + +/** + * Check if a given object implements the ChainflipBaasStatusSwap interface. + */ +export function instanceOfChainflipBaasStatusSwap(value: object): boolean { + let isInstance = true; + + return isInstance; +} + +export function ChainflipBaasStatusSwapFromJSON(json: any): ChainflipBaasStatusSwap { + return ChainflipBaasStatusSwapFromJSONTyped(json, false); +} + +export function ChainflipBaasStatusSwapFromJSONTyped(json: any, ignoreDiscriminator: boolean): ChainflipBaasStatusSwap { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'originalInputAmountNative': !exists(json, 'originalInputAmountNative') ? undefined : json['originalInputAmountNative'], + 'originalInputAmount': !exists(json, 'originalInputAmount') ? undefined : json['originalInputAmount'], + 'remainingInputAmountNative': !exists(json, 'remainingInputAmountNative') ? undefined : json['remainingInputAmountNative'], + 'remainingInputAmount': !exists(json, 'remainingInputAmount') ? undefined : json['remainingInputAmount'], + 'swappedInputAmountNative': !exists(json, 'swappedInputAmountNative') ? undefined : json['swappedInputAmountNative'], + 'swappedInputAmount': !exists(json, 'swappedInputAmount') ? undefined : json['swappedInputAmount'], + 'swappedIntermediateAmountNative': !exists(json, 'swappedIntermediateAmountNative') ? undefined : json['swappedIntermediateAmountNative'], + 'swappedIntermediateAmount': !exists(json, 'swappedIntermediateAmount') ? undefined : json['swappedIntermediateAmount'], + 'swappedOutputAmountNative': !exists(json, 'swappedOutputAmountNative') ? undefined : json['swappedOutputAmountNative'], + 'swappedOutputAmount': !exists(json, 'swappedOutputAmount') ? undefined : json['swappedOutputAmount'], + 'regular': !exists(json, 'regular') ? undefined : ChainflipBaasStatusChunkInfoFromJSON(json['regular']), + 'dca': !exists(json, 'dca') ? undefined : ChainflipBaasStatusDcaFromJSON(json['dca']), + }; +} + +export function ChainflipBaasStatusSwapToJSON(value?: ChainflipBaasStatusSwap | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'originalInputAmountNative': value.originalInputAmountNative, + 'originalInputAmount': value.originalInputAmount, + 'remainingInputAmountNative': value.remainingInputAmountNative, + 'remainingInputAmount': value.remainingInputAmount, + 'swappedInputAmountNative': value.swappedInputAmountNative, + 'swappedInputAmount': value.swappedInputAmount, + 'swappedIntermediateAmountNative': value.swappedIntermediateAmountNative, + 'swappedIntermediateAmount': value.swappedIntermediateAmount, + 'swappedOutputAmountNative': value.swappedOutputAmountNative, + 'swappedOutputAmount': value.swappedOutputAmount, + 'regular': ChainflipBaasStatusChunkInfoToJSON(value.regular), + 'dca': ChainflipBaasStatusDcaToJSON(value.dca), + }; +} + diff --git a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusSwapStatus.ts b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusSwapStatus.ts new file mode 100644 index 00000000000..e8ff95929fa --- /dev/null +++ b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusSwapStatus.ts @@ -0,0 +1,243 @@ +// @ts-nocheck +/* tslint:disable */ +/* eslint-disable */ +/** + * Chainflip Broker as a Service + * Run your own Chainflip Broker without any hassle. + * + * The version of the OpenAPI document: v1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +import type { ChainflipBaasStatusBoost } from './ChainflipBaasStatusBoost'; +import { + ChainflipBaasStatusBoostFromJSON, + ChainflipBaasStatusBoostFromJSONTyped, + ChainflipBaasStatusBoostToJSON, +} from './ChainflipBaasStatusBoost'; +import type { ChainflipBaasStatusCcmParameters } from './ChainflipBaasStatusCcmParameters'; +import { + ChainflipBaasStatusCcmParametersFromJSON, + ChainflipBaasStatusCcmParametersFromJSONTyped, + ChainflipBaasStatusCcmParametersToJSON, +} from './ChainflipBaasStatusCcmParameters'; +import type { ChainflipBaasStatusDeposit } from './ChainflipBaasStatusDeposit'; +import { + ChainflipBaasStatusDepositFromJSON, + ChainflipBaasStatusDepositFromJSONTyped, + ChainflipBaasStatusDepositToJSON, +} from './ChainflipBaasStatusDeposit'; +import type { ChainflipBaasStatusDepositChannel } from './ChainflipBaasStatusDepositChannel'; +import { + ChainflipBaasStatusDepositChannelFromJSON, + ChainflipBaasStatusDepositChannelFromJSONTyped, + ChainflipBaasStatusDepositChannelToJSON, +} from './ChainflipBaasStatusDepositChannel'; +import type { ChainflipBaasStatusEgress } from './ChainflipBaasStatusEgress'; +import { + ChainflipBaasStatusEgressFromJSON, + ChainflipBaasStatusEgressFromJSONTyped, + ChainflipBaasStatusEgressToJSON, +} from './ChainflipBaasStatusEgress'; +import type { ChainflipBaasStatusPaidFee } from './ChainflipBaasStatusPaidFee'; +import { + ChainflipBaasStatusPaidFeeFromJSON, + ChainflipBaasStatusPaidFeeFromJSONTyped, + ChainflipBaasStatusPaidFeeToJSON, +} from './ChainflipBaasStatusPaidFee'; +import type { ChainflipBaasStatusSwap } from './ChainflipBaasStatusSwap'; +import { + ChainflipBaasStatusSwapFromJSON, + ChainflipBaasStatusSwapFromJSONTyped, + ChainflipBaasStatusSwapToJSON, +} from './ChainflipBaasStatusSwap'; + +/** + * + * @export + * @interface ChainflipBaasStatusSwapStatus + */ +export interface ChainflipBaasStatusSwapStatus { + /** + * + * @type {string} + * @memberof ChainflipBaasStatusSwapStatus + */ + readonly state?: ChainflipBaasStatusSwapStatusStateEnum; + /** + * + * @type {string} + * @memberof ChainflipBaasStatusSwapStatus + */ + readonly swapId?: string; + /** + * + * @type {string} + * @memberof ChainflipBaasStatusSwapStatus + */ + readonly sourceAsset?: string; + /** + * + * @type {string} + * @memberof ChainflipBaasStatusSwapStatus + */ + readonly destinationAsset?: string; + /** + * + * @type {string} + * @memberof ChainflipBaasStatusSwapStatus + */ + readonly destinationAddress?: string; + /** + * + * @type {ChainflipBaasStatusDepositChannel} + * @memberof ChainflipBaasStatusSwapStatus + */ + depositChannel?: ChainflipBaasStatusDepositChannel; + /** + * + * @type {ChainflipBaasStatusCcmParameters} + * @memberof ChainflipBaasStatusSwapStatus + */ + ccmParams?: ChainflipBaasStatusCcmParameters; + /** + * + * @type {ChainflipBaasStatusBoost} + * @memberof ChainflipBaasStatusSwapStatus + */ + boost?: ChainflipBaasStatusBoost; + /** + * + * @type {number} + * @memberof ChainflipBaasStatusSwapStatus + */ + readonly estimatedDurationSeconds?: number | null; + /** + * + * @type {number} + * @memberof ChainflipBaasStatusSwapStatus + */ + readonly sourceChainRequiredBlockConfirmations?: number | null; + /** + * + * @type {Array} + * @memberof ChainflipBaasStatusSwapStatus + */ + readonly fees?: Array | null; + /** + * + * @type {ChainflipBaasStatusDeposit} + * @memberof ChainflipBaasStatusSwapStatus + */ + deposit?: ChainflipBaasStatusDeposit; + /** + * + * @type {ChainflipBaasStatusSwap} + * @memberof ChainflipBaasStatusSwapStatus + */ + swap?: ChainflipBaasStatusSwap; + /** + * + * @type {ChainflipBaasStatusEgress} + * @memberof ChainflipBaasStatusSwapStatus + */ + swapEgress?: ChainflipBaasStatusEgress; + /** + * + * @type {ChainflipBaasStatusEgress} + * @memberof ChainflipBaasStatusSwapStatus + */ + refundEgress?: ChainflipBaasStatusEgress; + /** + * + * @type {number} + * @memberof ChainflipBaasStatusSwapStatus + */ + readonly lastStateChainUpdateAt?: number | null; + /** + * + * @type {Date} + * @memberof ChainflipBaasStatusSwapStatus + */ + readonly lastStateChainUpdateAtDate?: Date | null; +} + + +/** + * @export + */ +export const ChainflipBaasStatusSwapStatusStateEnum = { + Waiting: 'waiting', + Receiving: 'receiving', + Swapping: 'swapping', + Sending: 'sending', + Sent: 'sent', + Completed: 'completed', + Failed: 'failed' +} as const; +export type ChainflipBaasStatusSwapStatusStateEnum = typeof ChainflipBaasStatusSwapStatusStateEnum[keyof typeof ChainflipBaasStatusSwapStatusStateEnum]; + + +/** + * Check if a given object implements the ChainflipBaasStatusSwapStatus interface. + */ +export function instanceOfChainflipBaasStatusSwapStatus(value: object): boolean { + let isInstance = true; + + return isInstance; +} + +export function ChainflipBaasStatusSwapStatusFromJSON(json: any): ChainflipBaasStatusSwapStatus { + return ChainflipBaasStatusSwapStatusFromJSONTyped(json, false); +} + +export function ChainflipBaasStatusSwapStatusFromJSONTyped(json: any, ignoreDiscriminator: boolean): ChainflipBaasStatusSwapStatus { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'state': !exists(json, 'state') ? undefined : json['state'], + 'swapId': !exists(json, 'swapId') ? undefined : json['swapId'], + 'sourceAsset': !exists(json, 'sourceAsset') ? undefined : json['sourceAsset'], + 'destinationAsset': !exists(json, 'destinationAsset') ? undefined : json['destinationAsset'], + 'destinationAddress': !exists(json, 'destinationAddress') ? undefined : json['destinationAddress'], + 'depositChannel': !exists(json, 'depositChannel') ? undefined : ChainflipBaasStatusDepositChannelFromJSON(json['depositChannel']), + 'ccmParams': !exists(json, 'ccmParams') ? undefined : ChainflipBaasStatusCcmParametersFromJSON(json['ccmParams']), + 'boost': !exists(json, 'boost') ? undefined : ChainflipBaasStatusBoostFromJSON(json['boost']), + 'estimatedDurationSeconds': !exists(json, 'estimatedDurationSeconds') ? undefined : json['estimatedDurationSeconds'], + 'sourceChainRequiredBlockConfirmations': !exists(json, 'sourceChainRequiredBlockConfirmations') ? undefined : json['sourceChainRequiredBlockConfirmations'], + 'fees': !exists(json, 'fees') ? undefined : (json['fees'] === null ? null : (json['fees'] as Array).map(ChainflipBaasStatusPaidFeeFromJSON)), + 'deposit': !exists(json, 'deposit') ? undefined : ChainflipBaasStatusDepositFromJSON(json['deposit']), + 'swap': !exists(json, 'swap') ? undefined : ChainflipBaasStatusSwapFromJSON(json['swap']), + 'swapEgress': !exists(json, 'swapEgress') ? undefined : ChainflipBaasStatusEgressFromJSON(json['swapEgress']), + 'refundEgress': !exists(json, 'refundEgress') ? undefined : ChainflipBaasStatusEgressFromJSON(json['refundEgress']), + 'lastStateChainUpdateAt': !exists(json, 'lastStateChainUpdateAt') ? undefined : json['lastStateChainUpdateAt'], + 'lastStateChainUpdateAtDate': !exists(json, 'lastStateChainUpdateAtDate') ? undefined : (json['lastStateChainUpdateAtDate'] === null ? null : new Date(json['lastStateChainUpdateAtDate'])), + }; +} + +export function ChainflipBaasStatusSwapStatusToJSON(value?: ChainflipBaasStatusSwapStatus | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'depositChannel': ChainflipBaasStatusDepositChannelToJSON(value.depositChannel), + 'ccmParams': ChainflipBaasStatusCcmParametersToJSON(value.ccmParams), + 'boost': ChainflipBaasStatusBoostToJSON(value.boost), + 'deposit': ChainflipBaasStatusDepositToJSON(value.deposit), + 'swap': ChainflipBaasStatusSwapToJSON(value.swap), + 'swapEgress': ChainflipBaasStatusEgressToJSON(value.swapEgress), + 'refundEgress': ChainflipBaasStatusEgressToJSON(value.refundEgress), + }; +} + diff --git a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasSwapAdvancedSwapRequest.ts b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasSwapAdvancedSwapRequest.ts new file mode 100644 index 00000000000..e14fa34be2e --- /dev/null +++ b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasSwapAdvancedSwapRequest.ts @@ -0,0 +1,73 @@ +// @ts-nocheck +/* tslint:disable */ +/* eslint-disable */ +/** + * Chainflip Broker as a Service + * Run your own Chainflip Broker without any hassle. + * + * The version of the OpenAPI document: v1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +import type { ChainflipBaasSwapCcmRequest } from './ChainflipBaasSwapCcmRequest'; +import { + ChainflipBaasSwapCcmRequestFromJSON, + ChainflipBaasSwapCcmRequestFromJSONTyped, + ChainflipBaasSwapCcmRequestToJSON, +} from './ChainflipBaasSwapCcmRequest'; + +/** + * + * @export + * @interface ChainflipBaasSwapAdvancedSwapRequest + */ +export interface ChainflipBaasSwapAdvancedSwapRequest { + /** + * + * @type {ChainflipBaasSwapCcmRequest} + * @memberof ChainflipBaasSwapAdvancedSwapRequest + */ + ccmPayload?: ChainflipBaasSwapCcmRequest; +} + +/** + * Check if a given object implements the ChainflipBaasSwapAdvancedSwapRequest interface. + */ +export function instanceOfChainflipBaasSwapAdvancedSwapRequest(value: object): boolean { + let isInstance = true; + + return isInstance; +} + +export function ChainflipBaasSwapAdvancedSwapRequestFromJSON(json: any): ChainflipBaasSwapAdvancedSwapRequest { + return ChainflipBaasSwapAdvancedSwapRequestFromJSONTyped(json, false); +} + +export function ChainflipBaasSwapAdvancedSwapRequestFromJSONTyped(json: any, ignoreDiscriminator: boolean): ChainflipBaasSwapAdvancedSwapRequest { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'ccmPayload': !exists(json, 'ccmPayload') ? undefined : ChainflipBaasSwapCcmRequestFromJSON(json['ccmPayload']), + }; +} + +export function ChainflipBaasSwapAdvancedSwapRequestToJSON(value?: ChainflipBaasSwapAdvancedSwapRequest | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'ccmPayload': ChainflipBaasSwapCcmRequestToJSON(value.ccmPayload), + }; +} + diff --git a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasSwapCcmRequest.ts b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasSwapCcmRequest.ts new file mode 100644 index 00000000000..ebab52a8947 --- /dev/null +++ b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasSwapCcmRequest.ts @@ -0,0 +1,76 @@ +// @ts-nocheck +/* tslint:disable */ +/* eslint-disable */ +/** + * Chainflip Broker as a Service + * Run your own Chainflip Broker without any hassle. + * + * The version of the OpenAPI document: v1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +/** + * Cross-Chain Messaging payload. More details can be found at https://docs.chainflip.io/swapping/integrations/advanced/cross-chain-messaging/cross-chain-messaging + * @export + * @interface ChainflipBaasSwapCcmRequest + */ +export interface ChainflipBaasSwapCcmRequest { + /** + * Gas budget for the call on the destination chain. This amount is based on the source asset and will be subtracted from the input amount and swapped to pay for gas. + * @type {string} + * @memberof ChainflipBaasSwapCcmRequest + */ + gasBudget: string; + /** + * Hex-encoded message that is passed to the destination address on the destination chain. The message should be shorter than 10k bytes. + * @type {string} + * @memberof ChainflipBaasSwapCcmRequest + */ + message: string; +} + +/** + * Check if a given object implements the ChainflipBaasSwapCcmRequest interface. + */ +export function instanceOfChainflipBaasSwapCcmRequest(value: object): boolean { + let isInstance = true; + isInstance = isInstance && "gasBudget" in value; + isInstance = isInstance && "message" in value; + + return isInstance; +} + +export function ChainflipBaasSwapCcmRequestFromJSON(json: any): ChainflipBaasSwapCcmRequest { + return ChainflipBaasSwapCcmRequestFromJSONTyped(json, false); +} + +export function ChainflipBaasSwapCcmRequestFromJSONTyped(json: any, ignoreDiscriminator: boolean): ChainflipBaasSwapCcmRequest { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'gasBudget': json['gas_budget'], + 'message': json['message'], + }; +} + +export function ChainflipBaasSwapCcmRequestToJSON(value?: ChainflipBaasSwapCcmRequest | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'gas_budget': value.gasBudget, + 'message': value.message, + }; +} + diff --git a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasSwapDepositAddress.ts b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasSwapDepositAddress.ts new file mode 100644 index 00000000000..903dd8a07ea --- /dev/null +++ b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasSwapDepositAddress.ts @@ -0,0 +1,122 @@ +// @ts-nocheck +/* tslint:disable */ +/* eslint-disable */ +/** + * Chainflip Broker as a Service + * Run your own Chainflip Broker without any hassle. + * + * The version of the OpenAPI document: v1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +/** + * + * @export + * @interface ChainflipBaasSwapDepositAddress + */ +export interface ChainflipBaasSwapDepositAddress { + /** + * The swap id used to follow up status. + * @type {number} + * @memberof ChainflipBaasSwapDepositAddress + */ + id?: number | null; + /** + * The deposit address to send source assets to. + * @type {string} + * @memberof ChainflipBaasSwapDepositAddress + */ + readonly address?: string; + /** + * The block in which the deposit address was issued. + * @type {number} + * @memberof ChainflipBaasSwapDepositAddress + */ + readonly issuedBlock?: number; + /** + * The network to send the source assets over. + * @type {string} + * @memberof ChainflipBaasSwapDepositAddress + */ + readonly network?: string; + /** + * The channel id to monitor the deposit. + * @type {number} + * @memberof ChainflipBaasSwapDepositAddress + */ + readonly channelId?: number; + /** + * The block (on the source network) in which the deposit address will expire. + * @type {number} + * @memberof ChainflipBaasSwapDepositAddress + */ + readonly sourceExpiryBlock?: number; + /** + * The explorer url to monitor the deposit. + * @type {string} + * @memberof ChainflipBaasSwapDepositAddress + */ + readonly explorerUrl?: string; + /** + * Fee in $FLIP to open the deposit channel. + * @type {number} + * @memberof ChainflipBaasSwapDepositAddress + */ + readonly channelOpeningFee?: number; + /** + * Fee in $FLIP flipperinos to open the deposit channel. + * @type {string} + * @memberof ChainflipBaasSwapDepositAddress + */ + readonly channelOpeningFeeNative?: string; +} + +/** + * Check if a given object implements the ChainflipBaasSwapDepositAddress interface. + */ +export function instanceOfChainflipBaasSwapDepositAddress(value: object): boolean { + let isInstance = true; + + return isInstance; +} + +export function ChainflipBaasSwapDepositAddressFromJSON(json: any): ChainflipBaasSwapDepositAddress { + return ChainflipBaasSwapDepositAddressFromJSONTyped(json, false); +} + +export function ChainflipBaasSwapDepositAddressFromJSONTyped(json: any, ignoreDiscriminator: boolean): ChainflipBaasSwapDepositAddress { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'id': !exists(json, 'id') ? undefined : json['id'], + 'address': !exists(json, 'address') ? undefined : json['address'], + 'issuedBlock': !exists(json, 'issuedBlock') ? undefined : json['issuedBlock'], + 'network': !exists(json, 'network') ? undefined : json['network'], + 'channelId': !exists(json, 'channelId') ? undefined : json['channelId'], + 'sourceExpiryBlock': !exists(json, 'sourceExpiryBlock') ? undefined : json['sourceExpiryBlock'], + 'explorerUrl': !exists(json, 'explorerUrl') ? undefined : json['explorerUrl'], + 'channelOpeningFee': !exists(json, 'channelOpeningFee') ? undefined : json['channelOpeningFee'], + 'channelOpeningFeeNative': !exists(json, 'channelOpeningFeeNative') ? undefined : json['channelOpeningFeeNative'], + }; +} + +export function ChainflipBaasSwapDepositAddressToJSON(value?: ChainflipBaasSwapDepositAddress | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'id': value.id, + }; +} + diff --git a/packages/swapper/src/swappers/ChainflipSwapper/models/MicrosoftAspNetCoreMvcProblemDetails.ts b/packages/swapper/src/swappers/ChainflipSwapper/models/MicrosoftAspNetCoreMvcProblemDetails.ts new file mode 100644 index 00000000000..04af0af71e5 --- /dev/null +++ b/packages/swapper/src/swappers/ChainflipSwapper/models/MicrosoftAspNetCoreMvcProblemDetails.ts @@ -0,0 +1,101 @@ +// @ts-nocheck +/* tslint:disable */ +/* eslint-disable */ +/** + * Chainflip Broker as a Service + * Run your own Chainflip Broker without any hassle. + * + * The version of the OpenAPI document: v1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +/** + * + * @export + * @interface MicrosoftAspNetCoreMvcProblemDetails + */ +export interface MicrosoftAspNetCoreMvcProblemDetails { + [key: string]: any | any; + /** + * A URI reference [RFC3986] that identifies the problem type. This specification encourages that, when dereferenced, it provide human-readable documentation for the problem type (e.g., using HTML [W3C.REC-html5-20141028]). When this member is not present, its value is assumed to be "about:blank". + * @type {string} + * @memberof MicrosoftAspNetCoreMvcProblemDetails + */ + type?: string | null; + /** + * A short, human-readable summary of the problem type. It SHOULD NOT change from occurrence to occurrence of the problem, except for purposes of localization(e.g., using proactive content negotiation; see[RFC7231], Section 3.4). + * @type {string} + * @memberof MicrosoftAspNetCoreMvcProblemDetails + */ + title?: string | null; + /** + * The HTTP status code([RFC7231], Section 6) generated by the origin server for this occurrence of the problem. + * @type {number} + * @memberof MicrosoftAspNetCoreMvcProblemDetails + */ + status?: number | null; + /** + * A human-readable explanation specific to this occurrence of the problem. + * @type {string} + * @memberof MicrosoftAspNetCoreMvcProblemDetails + */ + detail?: string | null; + /** + * A URI reference that identifies the specific occurrence of the problem. It may or may not yield further information if dereferenced. + * @type {string} + * @memberof MicrosoftAspNetCoreMvcProblemDetails + */ + instance?: string | null; +} + +/** + * Check if a given object implements the MicrosoftAspNetCoreMvcProblemDetails interface. + */ +export function instanceOfMicrosoftAspNetCoreMvcProblemDetails(value: object): boolean { + let isInstance = true; + + return isInstance; +} + +export function MicrosoftAspNetCoreMvcProblemDetailsFromJSON(json: any): MicrosoftAspNetCoreMvcProblemDetails { + return MicrosoftAspNetCoreMvcProblemDetailsFromJSONTyped(json, false); +} + +export function MicrosoftAspNetCoreMvcProblemDetailsFromJSONTyped(json: any, ignoreDiscriminator: boolean): MicrosoftAspNetCoreMvcProblemDetails { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + ...json, + 'type': !exists(json, 'type') ? undefined : json['type'], + 'title': !exists(json, 'title') ? undefined : json['title'], + 'status': !exists(json, 'status') ? undefined : json['status'], + 'detail': !exists(json, 'detail') ? undefined : json['detail'], + 'instance': !exists(json, 'instance') ? undefined : json['instance'], + }; +} + +export function MicrosoftAspNetCoreMvcProblemDetailsToJSON(value?: MicrosoftAspNetCoreMvcProblemDetails | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + ...value, + 'type': value.type, + 'title': value.title, + 'status': value.status, + 'detail': value.detail, + 'instance': value.instance, + }; +} + diff --git a/packages/swapper/src/swappers/ChainflipSwapper/models/MicrosoftAspNetCoreMvcValidationProblemDetails.ts b/packages/swapper/src/swappers/ChainflipSwapper/models/MicrosoftAspNetCoreMvcValidationProblemDetails.ts new file mode 100644 index 00000000000..60c433ef5e9 --- /dev/null +++ b/packages/swapper/src/swappers/ChainflipSwapper/models/MicrosoftAspNetCoreMvcValidationProblemDetails.ts @@ -0,0 +1,109 @@ +// @ts-nocheck +/* tslint:disable */ +/* eslint-disable */ +/** + * Chainflip Broker as a Service + * Run your own Chainflip Broker without any hassle. + * + * The version of the OpenAPI document: v1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +/** + * + * @export + * @interface MicrosoftAspNetCoreMvcValidationProblemDetails + */ +export interface MicrosoftAspNetCoreMvcValidationProblemDetails { + [key: string]: any | any; + /** + * A URI reference [RFC3986] that identifies the problem type. This specification encourages that, when dereferenced, it provide human-readable documentation for the problem type (e.g., using HTML [W3C.REC-html5-20141028]). When this member is not present, its value is assumed to be "about:blank". + * @type {string} + * @memberof MicrosoftAspNetCoreMvcValidationProblemDetails + */ + type?: string | null; + /** + * A short, human-readable summary of the problem type. It SHOULD NOT change from occurrence to occurrence of the problem, except for purposes of localization(e.g., using proactive content negotiation; see[RFC7231], Section 3.4). + * @type {string} + * @memberof MicrosoftAspNetCoreMvcValidationProblemDetails + */ + title?: string | null; + /** + * The HTTP status code([RFC7231], Section 6) generated by the origin server for this occurrence of the problem. + * @type {number} + * @memberof MicrosoftAspNetCoreMvcValidationProblemDetails + */ + status?: number | null; + /** + * A human-readable explanation specific to this occurrence of the problem. + * @type {string} + * @memberof MicrosoftAspNetCoreMvcValidationProblemDetails + */ + detail?: string | null; + /** + * A URI reference that identifies the specific occurrence of the problem. It may or may not yield further information if dereferenced. + * @type {string} + * @memberof MicrosoftAspNetCoreMvcValidationProblemDetails + */ + instance?: string | null; + /** + * The validation errors associated with this problem details. + * @type {{ [key: string]: Array; }} + * @memberof MicrosoftAspNetCoreMvcValidationProblemDetails + */ + errors?: { [key: string]: Array; }; +} + +/** + * Check if a given object implements the MicrosoftAspNetCoreMvcValidationProblemDetails interface. + */ +export function instanceOfMicrosoftAspNetCoreMvcValidationProblemDetails(value: object): boolean { + let isInstance = true; + + return isInstance; +} + +export function MicrosoftAspNetCoreMvcValidationProblemDetailsFromJSON(json: any): MicrosoftAspNetCoreMvcValidationProblemDetails { + return MicrosoftAspNetCoreMvcValidationProblemDetailsFromJSONTyped(json, false); +} + +export function MicrosoftAspNetCoreMvcValidationProblemDetailsFromJSONTyped(json: any, ignoreDiscriminator: boolean): MicrosoftAspNetCoreMvcValidationProblemDetails { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + ...json, + 'type': !exists(json, 'type') ? undefined : json['type'], + 'title': !exists(json, 'title') ? undefined : json['title'], + 'status': !exists(json, 'status') ? undefined : json['status'], + 'detail': !exists(json, 'detail') ? undefined : json['detail'], + 'instance': !exists(json, 'instance') ? undefined : json['instance'], + 'errors': !exists(json, 'errors') ? undefined : json['errors'], + }; +} + +export function MicrosoftAspNetCoreMvcValidationProblemDetailsToJSON(value?: MicrosoftAspNetCoreMvcValidationProblemDetails | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + ...value, + 'type': value.type, + 'title': value.title, + 'status': value.status, + 'detail': value.detail, + 'instance': value.instance, + 'errors': value.errors, + }; +} + diff --git a/packages/swapper/src/swappers/ChainflipSwapper/models/index.ts b/packages/swapper/src/swappers/ChainflipSwapper/models/index.ts new file mode 100644 index 00000000000..dc72788d43a --- /dev/null +++ b/packages/swapper/src/swappers/ChainflipSwapper/models/index.ts @@ -0,0 +1,36 @@ +// @ts-nocheck +/* tslint:disable */ +/* eslint-disable */ +export * from './ChainflipBaasAssetsAssetInfo'; +export * from './ChainflipBaasAssetsAssetsResponse'; +export * from './ChainflipBaasBalanceBalanceResponse'; +export * from './ChainflipBaasFeesFeesResponse'; +export * from './ChainflipBaasNetworksNetworkInfo'; +export * from './ChainflipBaasNetworksNetworksResponse'; +export * from './ChainflipBaasQuoteBoostQuote'; +export * from './ChainflipBaasQuotePoolFee'; +export * from './ChainflipBaasQuotePoolInfo'; +export * from './ChainflipBaasQuoteQuote'; +export * from './ChainflipBaasQuoteQuoteFee'; +export * from './ChainflipBaasRpcRpcRequest'; +export * from './ChainflipBaasStatusAffiliateBroker'; +export * from './ChainflipBaasStatusBoost'; +export * from './ChainflipBaasStatusCcmParameters'; +export * from './ChainflipBaasStatusChunkInfo'; +export * from './ChainflipBaasStatusDca'; +export * from './ChainflipBaasStatusDcaParameters'; +export * from './ChainflipBaasStatusDeposit'; +export * from './ChainflipBaasStatusDepositChannel'; +export * from './ChainflipBaasStatusEgress'; +export * from './ChainflipBaasStatusFailure'; +export * from './ChainflipBaasStatusFillOrKillParameters'; +export * from './ChainflipBaasStatusPaidFee'; +export * from './ChainflipBaasStatusReason'; +export * from './ChainflipBaasStatusStatusResponse'; +export * from './ChainflipBaasStatusSwap'; +export * from './ChainflipBaasStatusSwapStatus'; +export * from './ChainflipBaasSwapAdvancedSwapRequest'; +export * from './ChainflipBaasSwapCcmRequest'; +export * from './ChainflipBaasSwapDepositAddress'; +export * from './MicrosoftAspNetCoreMvcProblemDetails'; +export * from './MicrosoftAspNetCoreMvcValidationProblemDetails'; diff --git a/packages/swapper/src/swappers/ChainflipSwapper/utils/chainflipService.ts b/packages/swapper/src/swappers/ChainflipSwapper/utils/chainflipService.ts new file mode 100644 index 00000000000..365adf87f0a --- /dev/null +++ b/packages/swapper/src/swappers/ChainflipSwapper/utils/chainflipService.ts @@ -0,0 +1,19 @@ +import { SwapperName } from '../../../types' +import { createCache, makeSwapperAxiosServiceMonadic } from '../../../utils' + +const maxAge = 60 * 60 * 1000 // 1 hour cache for assets +const cachedUrls = [ + '/assets/', +] + +const axiosConfig = { + timeout: 10000, + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + }, +} + +const chainflipServiceBase = createCache(maxAge, cachedUrls, axiosConfig) + +export const chainflipService = makeSwapperAxiosServiceMonadic(chainflipServiceBase, SwapperName.Chainflip) diff --git a/packages/swapper/src/types.ts b/packages/swapper/src/types.ts index dcc93275946..f99cd8ec352 100644 --- a/packages/swapper/src/types.ts +++ b/packages/swapper/src/types.ts @@ -48,6 +48,7 @@ export type SwapperConfig = { REACT_APP_PORTALS_BASE_URL: string REACT_APP_FEATURE_ZRX_PERMIT2: boolean REACT_APP_ZRX_BASE_URL: string, + REACT_APP_CHAINFLIP_API_KEY: string REACT_APP_CHAINFLIP_API_URL: string REACT_APP_FEATURE_CHAINFLIP_BOOST_SWAPS: boolean REACT_APP_FEATURE_CHAINFLIP_DCA_SWAPS: boolean From 09b820d7047c395e4f8ebf8fc7a81723ba48774c Mon Sep 17 00:00:00 2001 From: David Cumps Date: Wed, 23 Oct 2024 15:41:35 +0200 Subject: [PATCH 011/127] feat: add fees to quotes --- .../swappers/ChainflipSwapper/constants.ts | 17 ++- .../getChainflipTradeQuote/getTradeQuote.ts | 137 +++++++++++++++--- 2 files changed, 135 insertions(+), 19 deletions(-) diff --git a/packages/swapper/src/swappers/ChainflipSwapper/constants.ts b/packages/swapper/src/swappers/ChainflipSwapper/constants.ts index 1ae1bab8453..c1ca84a857b 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/constants.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/constants.ts @@ -1,5 +1,5 @@ import type { ChainId } from '@shapeshiftoss/caip' -import { KnownChainIds } from "@shapeshiftoss/types"; +import { Asset, KnownChainIds } from "@shapeshiftoss/types"; import { SupportedChainIds, SwapperName, SwapSource } from '../../types' import { ChainflipSupportedChainIds } from './types' @@ -9,6 +9,7 @@ export const CHAINFLIP_SUPPORTED_CHAIN_IDS: SupportedChainIds = { buy: ChainflipSupportedChainIds as unknown as ChainId[], } +export const CHAINFLIP_SWAP_SOURCE: SwapSource = SwapperName.Chainflip; export const CHAINFLIP_BOOST_SWAP_SOURCE: SwapSource = `${SwapperName.Chainflip} • Boost` export const CHAINFLIP_DCA_SWAP_SOURCE: SwapSource = `${SwapperName.Chainflip} • DCA` export const CHAINFLIP_DCA_BOOST_SWAP_SOURCE: SwapSource = `${SwapperName.Chainflip} • DCA • Boost` @@ -20,3 +21,17 @@ export const chainIdToChainflipNetwork: Partial> = [KnownChainIds.SolanaMainnet]: 'sol', // TODO: Add Polkadot } + +export const usdcAsset: Asset = { + assetId: "eip155:1/erc20:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", + chainId: KnownChainIds.EthereumMainnet, + color: "#2373CB", + explorer:"https://etherscan.io", + explorerAddressLink:"https://etherscan.io/address/", + explorerTxLink:"https://etherscan.io/tx/", + icon:"https://rawcdn.githack.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png", + name:"USDC on Ethereum", + precision: 6, + relatedAssetKey: "eip155:1/erc20:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", + symbol:"USDC" +} \ No newline at end of file diff --git a/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts b/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts index 9a7f7e53516..601f80b4796 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts @@ -1,30 +1,38 @@ -import { Err, Result } from "@sniptt/monads"; +import { v4 as uuid } from "uuid"; +import { Err, Ok, Result } from "@sniptt/monads"; import { KnownChainIds } from "@shapeshiftoss/types"; +import type { AssetId } from "@shapeshiftoss/caip"; import { - GetTradeQuoteInput, - SwapErrorRight, - SwapperDeps, - TradeQuote, - TradeQuoteError + GetTradeQuoteInput, type ProtocolFee, + SwapErrorRight, + SwapperDeps, + TradeQuote, + TradeQuoteError } from "../../../types"; -import { makeSwapErrorRight } from "../../../utils"; -import { chainIdToChainflipNetwork } from "../constants"; +import { getRate, makeSwapErrorRight } from "../../../utils"; + +import { + CHAINFLIP_DCA_SWAP_SOURCE, + CHAINFLIP_SWAP_SOURCE, + chainIdToChainflipNetwork, + usdcAsset +} from "../constants"; import { isSupportedChainId, isSupportedAsset } from "../utils/helpers"; import { chainflipService } from "../utils/chainflipService"; -import { ChainflipBaasQuoteQuote } from "../models"; +import { ChainflipBaasQuoteQuote, ChainflipBaasQuoteQuoteFee } from "../models"; export const getChainflipTradeQuote = async ( - input: GetTradeQuoteInput, - deps: SwapperDeps, + input: GetTradeQuoteInput, + deps: SwapperDeps, ): Promise> => { const { sellAsset, - buyAsset, + buyAsset, sellAmountIncludingProtocolFeesCryptoBaseUnit: sellAmount, affiliateBps: commissionBps, } = input - + if (!isSupportedChainId(sellAsset.chainId)) { return Err( makeSwapErrorRight({ @@ -69,19 +77,112 @@ export const getChainflipTradeQuote = async ( const buyChainflipChainKey = `${buyAsset.symbol.toLowerCase()}.${chainIdToChainflipNetwork[buyAsset.chainId as KnownChainIds]}`; const brokerUrl = deps.config.REACT_APP_CHAINFLIP_API_URL - const apiKey = deps.config.REACT_APP_CHAINFLIP_API_KEY; + const apiKey = deps.config.REACT_APP_CHAINFLIP_API_KEY; - // @ts-ignore const maybeQuoteResponse = await chainflipService.get( `${brokerUrl}/quotes-native?apiKey=${apiKey}&sourceAsset=${sellChainflipChainKey}&destinationAsset=${buyChainflipChainKey}&amount=${sellAmount}&commissionBps=${commissionBps}`, ); - //if (maybeQuoteResponse.isErr()) { + if (maybeQuoteResponse.isErr()) { return Err( makeSwapErrorRight({ message: 'Quote request failed', code: TradeQuoteError.NoRouteFound, }), ) - //} -} \ No newline at end of file + } + + const { data: quoteResponse } = maybeQuoteResponse.unwrap() + + const getFeeAsset = (fee: ChainflipBaasQuoteQuoteFee) => { + if (fee.type === "ingress") + return sellAsset; + + if (fee.type === "egress") + return buyAsset; + + if (fee.type === "liquidity" && fee.asset == sellChainflipChainKey) + return sellAsset; + + if (fee.type === "liquidity" && fee.asset == buyChainflipChainKey) + return sellAsset; + + if (fee.type === "liquidity" && fee.asset == "usdc.eth") + return usdcAsset; + + if (fee.type === "network") + return usdcAsset; + } + + const getProtocolFees = (singleQuoteResponse: ChainflipBaasQuoteQuote) => { + const protocolFees: Record = {} + + for (const fee of singleQuoteResponse.includedFees!) { + if (fee.type === "broker") + continue; + + const asset = getFeeAsset(fee)! + if (!(asset.assetId in protocolFees)) { + protocolFees[asset.assetId] = { + amountCryptoBaseUnit: "0", + requiresBalance: false, + asset: asset, + } + } + + protocolFees[asset.assetId].amountCryptoBaseUnit = + (BigInt(protocolFees[asset.assetId].amountCryptoBaseUnit) + BigInt(fee.amountNative!)).toString(); + } + + return protocolFees; + } + + const quotes = quoteResponse.map(singleQuoteResponse => { + const rate = getRate({ + sellAmountCryptoBaseUnit: singleQuoteResponse.ingressAmountNative!, + buyAmountCryptoBaseUnit: singleQuoteResponse.egressAmountNative!, + sellAsset, + buyAsset, + }) + + const isStreaming = singleQuoteResponse.type === "dca"; + + const swapSource = singleQuoteResponse.type === "regular" + ? CHAINFLIP_SWAP_SOURCE + : CHAINFLIP_DCA_SWAP_SOURCE; + + // TODO: If boostQuote is present, add that too, might have to change map to a foreach + + const tradeQuote: TradeQuote = { + id: uuid(), + rate: rate, + receiveAddress: "", + potentialAffiliateBps: commissionBps, + affiliateBps: commissionBps, + isStreaming: isStreaming, + slippageTolerancePercentageDecimal: undefined, + steps: [ + { + buyAmountBeforeFeesCryptoBaseUnit: "0", // TODO: Calculate egress - fees + buyAmountAfterFeesCryptoBaseUnit: singleQuoteResponse.egressAmountNative!, + sellAmountIncludingProtocolFeesCryptoBaseUnit: singleQuoteResponse.ingressAmountNative!, + feeData: { + networkFeeCryptoBaseUnit: undefined, + protocolFees: getProtocolFees(singleQuoteResponse), + }, + rate: rate, + source: swapSource, + buyAsset: buyAsset, + sellAsset: sellAsset, + accountNumber: 0, + allowanceContract: "", + estimatedExecutionTimeMs: singleQuoteResponse.estimatedDurationSeconds! * 1000 + } + ] + }; + + return tradeQuote; + }) + + return Ok(quotes); +} From 9f6059435866b19bcd85531b3bdf99a40b34bdaf Mon Sep 17 00:00:00 2001 From: David Cumps Date: Wed, 23 Oct 2024 16:05:49 +0200 Subject: [PATCH 012/127] feat: add boost swaps --- .../getChainflipTradeQuote/getTradeQuote.ts | 67 ++++++++++++++++--- 1 file changed, 56 insertions(+), 11 deletions(-) diff --git a/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts b/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts index 601f80b4796..65ac4f4c0f7 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts @@ -13,8 +13,10 @@ import { import { getRate, makeSwapErrorRight } from "../../../utils"; import { - CHAINFLIP_DCA_SWAP_SOURCE, CHAINFLIP_SWAP_SOURCE, + CHAINFLIP_BOOST_SWAP_SOURCE, + CHAINFLIP_DCA_SWAP_SOURCE, + CHAINFLIP_DCA_BOOST_SWAP_SOURCE, chainIdToChainflipNetwork, usdcAsset } from "../constants"; @@ -95,7 +97,7 @@ export const getChainflipTradeQuote = async ( const { data: quoteResponse } = maybeQuoteResponse.unwrap() const getFeeAsset = (fee: ChainflipBaasQuoteQuoteFee) => { - if (fee.type === "ingress") + if (fee.type === "ingress" || fee.type === "boost") return sellAsset; if (fee.type === "egress") @@ -105,7 +107,7 @@ export const getChainflipTradeQuote = async ( return sellAsset; if (fee.type === "liquidity" && fee.asset == buyChainflipChainKey) - return sellAsset; + return buyAsset; if (fee.type === "liquidity" && fee.asset == "usdc.eth") return usdcAsset; @@ -137,22 +139,65 @@ export const getChainflipTradeQuote = async ( return protocolFees; } - const quotes = quoteResponse.map(singleQuoteResponse => { + const quotes = []; + + for (const singleQuoteResponse of quoteResponse) { + const isStreaming = singleQuoteResponse.type === "dca"; + + if (singleQuoteResponse.boostQuote) { + const boostRate = getRate({ + sellAmountCryptoBaseUnit: singleQuoteResponse.boostQuote.ingressAmountNative!, + buyAmountCryptoBaseUnit: singleQuoteResponse.boostQuote.egressAmountNative!, + sellAsset, + buyAsset, + }) + + const boostSwapSource = singleQuoteResponse.type === "regular" + ? CHAINFLIP_BOOST_SWAP_SOURCE + : CHAINFLIP_DCA_BOOST_SWAP_SOURCE; + + const boostTradeQuote: TradeQuote = { + id: uuid(), + rate: boostRate, + receiveAddress: "", + potentialAffiliateBps: commissionBps, + affiliateBps: commissionBps, + isStreaming: isStreaming, + slippageTolerancePercentageDecimal: undefined, + steps: [ + { + buyAmountBeforeFeesCryptoBaseUnit: "0", + buyAmountAfterFeesCryptoBaseUnit: singleQuoteResponse.boostQuote.egressAmountNative!, + sellAmountIncludingProtocolFeesCryptoBaseUnit: singleQuoteResponse.boostQuote.ingressAmountNative!, + feeData: { + networkFeeCryptoBaseUnit: undefined, + protocolFees: getProtocolFees(singleQuoteResponse.boostQuote), + }, + rate: boostRate, + source: boostSwapSource, + buyAsset: buyAsset, + sellAsset: sellAsset, + accountNumber: 0, + allowanceContract: "", + estimatedExecutionTimeMs: singleQuoteResponse.boostQuote.estimatedDurationSeconds! * 1000 + } + ] + }; + + quotes.push(boostTradeQuote); + } + const rate = getRate({ sellAmountCryptoBaseUnit: singleQuoteResponse.ingressAmountNative!, buyAmountCryptoBaseUnit: singleQuoteResponse.egressAmountNative!, sellAsset, buyAsset, }) - - const isStreaming = singleQuoteResponse.type === "dca"; const swapSource = singleQuoteResponse.type === "regular" ? CHAINFLIP_SWAP_SOURCE : CHAINFLIP_DCA_SWAP_SOURCE; - // TODO: If boostQuote is present, add that too, might have to change map to a foreach - const tradeQuote: TradeQuote = { id: uuid(), rate: rate, @@ -163,7 +208,7 @@ export const getChainflipTradeQuote = async ( slippageTolerancePercentageDecimal: undefined, steps: [ { - buyAmountBeforeFeesCryptoBaseUnit: "0", // TODO: Calculate egress - fees + buyAmountBeforeFeesCryptoBaseUnit: "0", buyAmountAfterFeesCryptoBaseUnit: singleQuoteResponse.egressAmountNative!, sellAmountIncludingProtocolFeesCryptoBaseUnit: singleQuoteResponse.ingressAmountNative!, feeData: { @@ -181,8 +226,8 @@ export const getChainflipTradeQuote = async ( ] }; - return tradeQuote; - }) + quotes.push(tradeQuote); + } return Ok(quotes); } From 8bab08e9b0f8790f9e307a502b266974ea92581b Mon Sep 17 00:00:00 2001 From: David Cumps Date: Wed, 23 Oct 2024 16:09:03 +0200 Subject: [PATCH 013/127] fix: correct commissionBPs --- .../getChainflipTradeQuote/getTradeQuote.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts b/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts index 65ac4f4c0f7..ffc77d25155 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts @@ -80,9 +80,12 @@ export const getChainflipTradeQuote = async ( const brokerUrl = deps.config.REACT_APP_CHAINFLIP_API_URL const apiKey = deps.config.REACT_APP_CHAINFLIP_API_KEY; - + + // Subtract the 0.05% BaaS fee to end up at the final displayed commissionBps + const serviceCommission = parseInt(commissionBps) - 5; + const maybeQuoteResponse = await chainflipService.get( - `${brokerUrl}/quotes-native?apiKey=${apiKey}&sourceAsset=${sellChainflipChainKey}&destinationAsset=${buyChainflipChainKey}&amount=${sellAmount}&commissionBps=${commissionBps}`, + `${brokerUrl}/quotes-native?apiKey=${apiKey}&sourceAsset=${sellChainflipChainKey}&destinationAsset=${buyChainflipChainKey}&amount=${sellAmount}&commissionBps=${serviceCommission}`, ); if (maybeQuoteResponse.isErr()) { From 09b9b02b42e651f78f0a4d5676af99a35f8fcdb0 Mon Sep 17 00:00:00 2001 From: David Cumps Date: Wed, 23 Oct 2024 17:41:11 +0200 Subject: [PATCH 014/127] feat: first steps to get gas prices displayed --- .../getChainflipTradeQuote/getTradeQuote.ts | 51 ++++++++++++++++--- .../txFeeHelpers/evmTxFees/getEvmTxFees.ts | 19 +++++++ .../txFeeHelpers/utxoTxFees/getUtxoTxFees.ts | 31 +++++++++++ 3 files changed, 95 insertions(+), 6 deletions(-) create mode 100644 packages/swapper/src/swappers/ChainflipSwapper/txFeeHelpers/evmTxFees/getEvmTxFees.ts create mode 100644 packages/swapper/src/swappers/ChainflipSwapper/txFeeHelpers/utxoTxFees/getUtxoTxFees.ts diff --git a/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts b/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts index ffc77d25155..44195843939 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts @@ -1,9 +1,10 @@ import { v4 as uuid } from "uuid"; import { Err, Ok, Result } from "@sniptt/monads"; import { KnownChainIds } from "@shapeshiftoss/types"; -import type { AssetId } from "@shapeshiftoss/caip"; +import { AssetId, CHAIN_NAMESPACE, fromAssetId } from "@shapeshiftoss/caip"; import { + type GetEvmTradeQuoteInput, GetTradeQuoteInput, type ProtocolFee, SwapErrorRight, SwapperDeps, @@ -23,6 +24,8 @@ import { import { isSupportedChainId, isSupportedAsset } from "../utils/helpers"; import { chainflipService } from "../utils/chainflipService"; import { ChainflipBaasQuoteQuote, ChainflipBaasQuoteQuoteFee } from "../models"; +import { getEvmTxFees } from "../txFeeHelpers/evmTxFees/getEvmTxFees"; +// import { getUtxoTxFees } from "../txFeeHelpers/utxoTxFees/getUtxoTxFees"; export const getChainflipTradeQuote = async ( input: GetTradeQuoteInput, @@ -82,7 +85,9 @@ export const getChainflipTradeQuote = async ( const apiKey = deps.config.REACT_APP_CHAINFLIP_API_KEY; // Subtract the 0.05% BaaS fee to end up at the final displayed commissionBps - const serviceCommission = parseInt(commissionBps) - 5; + let serviceCommission = parseInt(commissionBps) - 5; + if (serviceCommission < 0) + serviceCommission = 0; const maybeQuoteResponse = await chainflipService.get( `${brokerUrl}/quotes-native?apiKey=${apiKey}&sourceAsset=${sellChainflipChainKey}&destinationAsset=${buyChainflipChainKey}&amount=${sellAmount}&commissionBps=${serviceCommission}`, @@ -98,7 +103,41 @@ export const getChainflipTradeQuote = async ( } const { data: quoteResponse } = maybeQuoteResponse.unwrap() + + const getGasFee = async () => { + const { chainNamespace } = fromAssetId(sellAsset.assetId); + + switch (chainNamespace) { + case CHAIN_NAMESPACE.Evm: { + const sellAdapter = deps.assertGetEvmChainAdapter(sellAsset.chainId); + return await getEvmTxFees({ + adapter: sellAdapter, + supportsEIP1559: (input as GetEvmTradeQuoteInput).supportsEIP1559, + }); + } + case CHAIN_NAMESPACE.Utxo: { + // TODO: Figure out BTC gas calc + return undefined; + // const sellAdapter = deps.assertGetUtxoChainAdapter(sellAsset.chainId) + // return await getUtxoTxFees({ + // sellAmountCryptoBaseUnit: sellAmount, + // vault, + // opReturnData, + // pubkey, + // sellAdapter, + // }) + } + + case CHAIN_NAMESPACE.Solana: { + // TODO: Solana gas calc + return undefined; + } + } + + return undefined; + } + const getFeeAsset = (fee: ChainflipBaasQuoteQuoteFee) => { if (fee.type === "ingress" || fee.type === "boost") return sellAsset; @@ -173,7 +212,7 @@ export const getChainflipTradeQuote = async ( buyAmountAfterFeesCryptoBaseUnit: singleQuoteResponse.boostQuote.egressAmountNative!, sellAmountIncludingProtocolFeesCryptoBaseUnit: singleQuoteResponse.boostQuote.ingressAmountNative!, feeData: { - networkFeeCryptoBaseUnit: undefined, + networkFeeCryptoBaseUnit: await getGasFee(), protocolFees: getProtocolFees(singleQuoteResponse.boostQuote), }, rate: boostRate, @@ -181,7 +220,7 @@ export const getChainflipTradeQuote = async ( buyAsset: buyAsset, sellAsset: sellAsset, accountNumber: 0, - allowanceContract: "", + allowanceContract: "0x0", // Chainflip does not use contracts estimatedExecutionTimeMs: singleQuoteResponse.boostQuote.estimatedDurationSeconds! * 1000 } ] @@ -200,7 +239,7 @@ export const getChainflipTradeQuote = async ( const swapSource = singleQuoteResponse.type === "regular" ? CHAINFLIP_SWAP_SOURCE : CHAINFLIP_DCA_SWAP_SOURCE; - + const tradeQuote: TradeQuote = { id: uuid(), rate: rate, @@ -215,7 +254,7 @@ export const getChainflipTradeQuote = async ( buyAmountAfterFeesCryptoBaseUnit: singleQuoteResponse.egressAmountNative!, sellAmountIncludingProtocolFeesCryptoBaseUnit: singleQuoteResponse.ingressAmountNative!, feeData: { - networkFeeCryptoBaseUnit: undefined, + networkFeeCryptoBaseUnit: await getGasFee(), protocolFees: getProtocolFees(singleQuoteResponse), }, rate: rate, diff --git a/packages/swapper/src/swappers/ChainflipSwapper/txFeeHelpers/evmTxFees/getEvmTxFees.ts b/packages/swapper/src/swappers/ChainflipSwapper/txFeeHelpers/evmTxFees/getEvmTxFees.ts new file mode 100644 index 00000000000..7f45affa02d --- /dev/null +++ b/packages/swapper/src/swappers/ChainflipSwapper/txFeeHelpers/evmTxFees/getEvmTxFees.ts @@ -0,0 +1,19 @@ +import type { EvmChainAdapter } from '@shapeshiftoss/chain-adapters' +import { evm } from '@shapeshiftoss/chain-adapters' + +type GetEvmTxFeesArgs = { + adapter: EvmChainAdapter + supportsEIP1559: boolean +} + +export const getEvmTxFees = async (args: GetEvmTxFeesArgs): Promise => { + const { adapter, supportsEIP1559 } = args + + const { average } = await adapter.getGasFeeData() + + return evm.calcNetworkFeeCryptoBaseUnit({ + ...average, + supportsEIP1559, + gasLimit: "100000", // TODO: Get gas limits based on ingress coins + }) +} diff --git a/packages/swapper/src/swappers/ChainflipSwapper/txFeeHelpers/utxoTxFees/getUtxoTxFees.ts b/packages/swapper/src/swappers/ChainflipSwapper/txFeeHelpers/utxoTxFees/getUtxoTxFees.ts new file mode 100644 index 00000000000..d63957087b4 --- /dev/null +++ b/packages/swapper/src/swappers/ChainflipSwapper/txFeeHelpers/utxoTxFees/getUtxoTxFees.ts @@ -0,0 +1,31 @@ +import type {GetFeeDataInput, UtxoChainAdapter} from '@shapeshiftoss/chain-adapters' +import type { UtxoChainId } from '@shapeshiftoss/types' +import { bn } from '@shapeshiftoss/utils' + +type GetUtxoTxFeesInput = { + opReturnData: string + vault: string + sellAmountCryptoBaseUnit: string + sellAdapter: UtxoChainAdapter + pubkey: string +} + +export const getUtxoTxFees = async ({ + opReturnData, + vault, + sellAmountCryptoBaseUnit, + sellAdapter, + pubkey, +}: GetUtxoTxFeesInput): Promise => { + const getFeeDataInput: GetFeeDataInput = { + to: vault, + value: sellAmountCryptoBaseUnit, + chainSpecific: { pubkey, opReturnData }, + } + + const feeDataOptions = await sellAdapter.getFeeData(getFeeDataInput) + + const feeData = feeDataOptions['fast'] + + return bn(feeData.txFee).dp(0).toString(); +} From e6a43accb1bdf681e3c6c640453655f97cfbaa11 Mon Sep 17 00:00:00 2001 From: David Cumps Date: Wed, 23 Oct 2024 17:48:25 +0200 Subject: [PATCH 015/127] fix: correct arb to eth --- packages/swapper/src/swappers/ChainflipSwapper/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/swapper/src/swappers/ChainflipSwapper/types.ts b/packages/swapper/src/swappers/ChainflipSwapper/types.ts index 24122596301..8217979fa25 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/types.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/types.ts @@ -12,7 +12,7 @@ export type ChainflipSupportedChainId = (typeof ChainflipSupportedChainIds)[numb export const ChainflipSupportedAssets = { [KnownChainIds.EthereumMainnet]: ['eth', 'flip', 'usdc', 'usdt'], - [KnownChainIds.ArbitrumMainnet]: ['arb', 'usdc'], + [KnownChainIds.ArbitrumMainnet]: ['eth', 'usdc'], [KnownChainIds.BitcoinMainnet]: ['btc'], [KnownChainIds.SolanaMainnet]: ['sol', 'usdc'], } \ No newline at end of file From 9c2f4471b22b00604dad7b9711997cd82ee72ab9 Mon Sep 17 00:00:00 2001 From: David Cumps Date: Wed, 23 Oct 2024 17:55:43 +0200 Subject: [PATCH 016/127] refactor: cleanup const and types --- .../ChainflipSwapper/ChainflipSwapper.ts | 2 -- .../swappers/ChainflipSwapper/constants.ts | 36 +++++++++++++------ .../src/swappers/ChainflipSwapper/types.ts | 18 ---------- .../ChainflipSwapper/utils/helpers.ts | 4 +-- 4 files changed, 28 insertions(+), 32 deletions(-) delete mode 100644 packages/swapper/src/swappers/ChainflipSwapper/types.ts diff --git a/packages/swapper/src/swappers/ChainflipSwapper/ChainflipSwapper.ts b/packages/swapper/src/swappers/ChainflipSwapper/ChainflipSwapper.ts index c39a13f0f03..634270f553f 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/ChainflipSwapper.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/ChainflipSwapper.ts @@ -6,7 +6,6 @@ import { CHAINFLIP_SUPPORTED_CHAIN_IDS } from './constants' export const chainflipSwapper: Swapper = { filterAssetIdsBySellable: (assets: Asset[]): Promise => { - // TODO: Return only Chainflip supported coins return Promise.resolve( assets .filter(asset => CHAINFLIP_SUPPORTED_CHAIN_IDS.sell.includes(asset.chainId)) @@ -15,7 +14,6 @@ export const chainflipSwapper: Swapper = { }, filterBuyAssetsBySellAssetId: (input: BuyAssetBySellIdInput): Promise => { - // TODO: Return only Chainflip supported coins return Promise.resolve( input.assets .filter(asset => CHAINFLIP_SUPPORTED_CHAIN_IDS.buy.includes(asset.chainId)) diff --git a/packages/swapper/src/swappers/ChainflipSwapper/constants.ts b/packages/swapper/src/swappers/ChainflipSwapper/constants.ts index c1ca84a857b..c63ccac3c22 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/constants.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/constants.ts @@ -1,18 +1,24 @@ import type { ChainId } from '@shapeshiftoss/caip' import { Asset, KnownChainIds } from "@shapeshiftoss/types"; - import { SupportedChainIds, SwapperName, SwapSource } from '../../types' -import { ChainflipSupportedChainIds } from './types' -export const CHAINFLIP_SUPPORTED_CHAIN_IDS: SupportedChainIds = { - sell: ChainflipSupportedChainIds as unknown as ChainId[], - buy: ChainflipSupportedChainIds as unknown as ChainId[], -} +export const ChainflipSupportedChainIds = [ + KnownChainIds.EthereumMainnet, + KnownChainIds.ArbitrumMainnet, + KnownChainIds.BitcoinMainnet, + KnownChainIds.SolanaMainnet, + // TODO: Add Polkadot +] as const -export const CHAINFLIP_SWAP_SOURCE: SwapSource = SwapperName.Chainflip; -export const CHAINFLIP_BOOST_SWAP_SOURCE: SwapSource = `${SwapperName.Chainflip} • Boost` -export const CHAINFLIP_DCA_SWAP_SOURCE: SwapSource = `${SwapperName.Chainflip} • DCA` -export const CHAINFLIP_DCA_BOOST_SWAP_SOURCE: SwapSource = `${SwapperName.Chainflip} • DCA • Boost` +export type ChainflipSupportedChainId = (typeof ChainflipSupportedChainIds)[number] + +export const ChainflipSupportedAssets = { + [KnownChainIds.EthereumMainnet]: ['eth', 'flip', 'usdc', 'usdt'], + [KnownChainIds.ArbitrumMainnet]: ['eth', 'usdc'], + [KnownChainIds.BitcoinMainnet]: ['btc'], + [KnownChainIds.SolanaMainnet]: ['sol', 'usdc'], + // TODO: Add Polkadot +} export const chainIdToChainflipNetwork: Partial> = { [KnownChainIds.EthereumMainnet]: 'eth', @@ -22,6 +28,16 @@ export const chainIdToChainflipNetwork: Partial> = // TODO: Add Polkadot } +export const CHAINFLIP_SUPPORTED_CHAIN_IDS: SupportedChainIds = { + sell: ChainflipSupportedChainIds as unknown as ChainId[], + buy: ChainflipSupportedChainIds as unknown as ChainId[], +} + +export const CHAINFLIP_SWAP_SOURCE: SwapSource = SwapperName.Chainflip; +export const CHAINFLIP_BOOST_SWAP_SOURCE: SwapSource = `${SwapperName.Chainflip} • Boost` +export const CHAINFLIP_DCA_SWAP_SOURCE: SwapSource = `${SwapperName.Chainflip} • DCA` +export const CHAINFLIP_DCA_BOOST_SWAP_SOURCE: SwapSource = `${SwapperName.Chainflip} • DCA • Boost` + export const usdcAsset: Asset = { assetId: "eip155:1/erc20:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", chainId: KnownChainIds.EthereumMainnet, diff --git a/packages/swapper/src/swappers/ChainflipSwapper/types.ts b/packages/swapper/src/swappers/ChainflipSwapper/types.ts deleted file mode 100644 index 8217979fa25..00000000000 --- a/packages/swapper/src/swappers/ChainflipSwapper/types.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { KnownChainIds } from '@shapeshiftoss/types' - -export const ChainflipSupportedChainIds = [ - KnownChainIds.EthereumMainnet, - KnownChainIds.ArbitrumMainnet, - KnownChainIds.BitcoinMainnet, - KnownChainIds.SolanaMainnet, - // TODO: Add Polkadot -] as const - -export type ChainflipSupportedChainId = (typeof ChainflipSupportedChainIds)[number] - -export const ChainflipSupportedAssets = { - [KnownChainIds.EthereumMainnet]: ['eth', 'flip', 'usdc', 'usdt'], - [KnownChainIds.ArbitrumMainnet]: ['eth', 'usdc'], - [KnownChainIds.BitcoinMainnet]: ['btc'], - [KnownChainIds.SolanaMainnet]: ['sol', 'usdc'], -} \ No newline at end of file diff --git a/packages/swapper/src/swappers/ChainflipSwapper/utils/helpers.ts b/packages/swapper/src/swappers/ChainflipSwapper/utils/helpers.ts index bf9d5856453..88a36236ab0 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/utils/helpers.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/utils/helpers.ts @@ -1,7 +1,7 @@ import { type ChainId } from '@shapeshiftoss/caip' -import type { ChainflipSupportedChainId } from '../types' -import { ChainflipSupportedChainIds, ChainflipSupportedAssets } from '../types' +import type { ChainflipSupportedChainId } from '../constants' +import { ChainflipSupportedChainIds, ChainflipSupportedAssets } from "../constants"; export const isSupportedChainId = (chainId: ChainId): chainId is ChainflipSupportedChainId => { return ChainflipSupportedChainIds.includes(chainId as ChainflipSupportedChainId) From 20216d6e026dd3b63b09ea84eed6b7a32d3a623b Mon Sep 17 00:00:00 2001 From: David Cumps Date: Wed, 23 Oct 2024 18:12:57 +0200 Subject: [PATCH 017/127] chore: add todo wrt minimum amounts --- .../ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts b/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts index 44195843939..c8de3a3ba31 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts @@ -93,6 +93,7 @@ export const getChainflipTradeQuote = async ( `${brokerUrl}/quotes-native?apiKey=${apiKey}&sourceAsset=${sellChainflipChainKey}&destinationAsset=${buyChainflipChainKey}&amount=${sellAmount}&commissionBps=${serviceCommission}`, ); + // TODO: Throw SellAmountBelowMinimum if that's the cause (parse error response) if (maybeQuoteResponse.isErr()) { return Err( makeSwapErrorRight({ From d5b9fee2e5dfdea158041e7889822f6eb3e29320 Mon Sep 17 00:00:00 2001 From: David Cumps Date: Wed, 23 Oct 2024 18:22:06 +0200 Subject: [PATCH 018/127] fix: deal with SellAmountBelowTradeFee error --- .../ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts b/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts index c8de3a3ba31..afe7b6e3d67 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts @@ -209,7 +209,7 @@ export const getChainflipTradeQuote = async ( slippageTolerancePercentageDecimal: undefined, steps: [ { - buyAmountBeforeFeesCryptoBaseUnit: "0", + buyAmountBeforeFeesCryptoBaseUnit: singleQuoteResponse.boostQuote.egressAmountNative!, buyAmountAfterFeesCryptoBaseUnit: singleQuoteResponse.boostQuote.egressAmountNative!, sellAmountIncludingProtocolFeesCryptoBaseUnit: singleQuoteResponse.boostQuote.ingressAmountNative!, feeData: { @@ -251,7 +251,7 @@ export const getChainflipTradeQuote = async ( slippageTolerancePercentageDecimal: undefined, steps: [ { - buyAmountBeforeFeesCryptoBaseUnit: "0", + buyAmountBeforeFeesCryptoBaseUnit: singleQuoteResponse.egressAmountNative!, buyAmountAfterFeesCryptoBaseUnit: singleQuoteResponse.egressAmountNative!, sellAmountIncludingProtocolFeesCryptoBaseUnit: singleQuoteResponse.ingressAmountNative!, feeData: { From 2861ba3f48a71be55de579fb5dd2a76807ccafa3 Mon Sep 17 00:00:00 2001 From: David Cumps Date: Wed, 23 Oct 2024 18:27:12 +0200 Subject: [PATCH 019/127] refactor: cleanup chainflip feature flag --- .env.base | 2 -- packages/swapper/src/types.ts | 2 -- src/config.ts | 2 -- src/state/slices/preferencesSlice/preferencesSlice.ts | 4 ---- src/test/mocks/store.ts | 2 -- 5 files changed, 12 deletions(-) diff --git a/.env.base b/.env.base index 244bc34f633..cb8f2c66562 100644 --- a/.env.base +++ b/.env.base @@ -59,8 +59,6 @@ REACT_APP_FEATURE_READ_ONLY_ASSETS=true # swapper feature flags - other .env files will override these REACT_APP_FEATURE_CHAINFLIP=true -REACT_APP_FEATURE_CHAINFLIP_BOOST_SWAPS=true -REACT_APP_FEATURE_CHAINFLIP_DCA_SWAPS=true REACT_APP_FEATURE_COWSWAP=true REACT_APP_FEATURE_LIFI_SWAP=true REACT_APP_FEATURE_ONE_INCH=false diff --git a/packages/swapper/src/types.ts b/packages/swapper/src/types.ts index f99cd8ec352..85525cfd37d 100644 --- a/packages/swapper/src/types.ts +++ b/packages/swapper/src/types.ts @@ -50,8 +50,6 @@ export type SwapperConfig = { REACT_APP_ZRX_BASE_URL: string, REACT_APP_CHAINFLIP_API_KEY: string REACT_APP_CHAINFLIP_API_URL: string - REACT_APP_FEATURE_CHAINFLIP_BOOST_SWAPS: boolean - REACT_APP_FEATURE_CHAINFLIP_DCA_SWAPS: boolean } export enum SwapperName { diff --git a/src/config.ts b/src/config.ts index d65e598158f..2e10251a1cf 100644 --- a/src/config.ts +++ b/src/config.ts @@ -178,8 +178,6 @@ const validators = { REACT_APP_FEATURE_LIMIT_ORDERS: bool({ default: false }), REACT_APP_ZRX_BASE_URL: url(), REACT_APP_FEATURE_CHAINFLIP: bool({ default: false }), - REACT_APP_FEATURE_CHAINFLIP_BOOST_SWAPS: bool({ default: false }), - REACT_APP_FEATURE_CHAINFLIP_DCA_SWAPS: bool({ default: false }), REACT_APP_CHAINFLIP_API_KEY: str({ default: '6ba154d4-e219-472a-9674-5fa5b1300ccf' }), REACT_APP_CHAINFLIP_API_URL: url({ default: 'https://chainflip-broker.io' }), } diff --git a/src/state/slices/preferencesSlice/preferencesSlice.ts b/src/state/slices/preferencesSlice/preferencesSlice.ts index 3b9c3779615..ea6ed45b70a 100644 --- a/src/state/slices/preferencesSlice/preferencesSlice.ts +++ b/src/state/slices/preferencesSlice/preferencesSlice.ts @@ -68,8 +68,6 @@ export type FeatureFlags = { FoxPageGovernance: boolean LimitOrders: boolean, Chainflip: boolean, - ChainflipBoostSwaps: boolean, - ChainflipDcaSwaps: boolean, } export type Flag = keyof FeatureFlags @@ -163,8 +161,6 @@ const initialState: Preferences = { FoxPageGovernance: getConfig().REACT_APP_FEATURE_FOX_PAGE_GOVERNANCE, LimitOrders: getConfig().REACT_APP_FEATURE_LIMIT_ORDERS, Chainflip: getConfig().REACT_APP_FEATURE_CHAINFLIP, - ChainflipBoostSwaps: getConfig().REACT_APP_FEATURE_CHAINFLIP_BOOST_SWAPS, - ChainflipDcaSwaps: getConfig().REACT_APP_FEATURE_CHAINFLIP_DCA_SWAPS, }, selectedLocale: simpleLocale(), balanceThreshold: '0', diff --git a/src/test/mocks/store.ts b/src/test/mocks/store.ts index 342a6430dd7..2d4d79ff31c 100644 --- a/src/test/mocks/store.ts +++ b/src/test/mocks/store.ts @@ -125,8 +125,6 @@ export const mockStore: ReduxState = { FoxPageGovernance: false, LimitOrders: false, Chainflip: false, - ChainflipBoostSwaps: false, - ChainflipDcaSwaps: false, }, selectedLocale: 'en', balanceThreshold: '0', From 57e08d1a1e204887e4868231b379dfa8be2046e3 Mon Sep 17 00:00:00 2001 From: David Cumps Date: Wed, 23 Oct 2024 23:34:16 +0200 Subject: [PATCH 020/127] refactor: move default chainflip settings to env --- .env.base | 5 ++++- src/config.ts | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/.env.base b/.env.base index cb8f2c66562..2b321b22dbb 100644 --- a/.env.base +++ b/.env.base @@ -151,7 +151,6 @@ REACT_APP_COVALENT_API_KEY=ckey_2160df0b81ac46e9a642b35a5f1 REACT_APP_FEATURE_COVALENT_JAYPEGS=true # Portals - REACT_APP_PORTALS_BASE_URL=https://api.portals.fi REACT_APP_PORTALS_API_KEY=bbc3ba7e-5f2a-4a0a-bbbc-22509944686c @@ -173,3 +172,7 @@ REACT_APP_ZERION_BASE_URL=https://api.proxy.shapeshift.com/api/v1/zerion # 0x REACT_APP_ZRX_BASE_URL=https://api.proxy.shapeshift.com/api/v1/zrx/ + +# chainflip +REACT_APP_CHAINFLIP_API_KEY=6ba154d4-e219-472a-9674-5fa5b1300ccf +REACT_APP_CHAINFLIP_API_URL=https://chainflip-broker.io \ No newline at end of file diff --git a/src/config.ts b/src/config.ts index 2e10251a1cf..aa596835709 100644 --- a/src/config.ts +++ b/src/config.ts @@ -178,8 +178,8 @@ const validators = { REACT_APP_FEATURE_LIMIT_ORDERS: bool({ default: false }), REACT_APP_ZRX_BASE_URL: url(), REACT_APP_FEATURE_CHAINFLIP: bool({ default: false }), - REACT_APP_CHAINFLIP_API_KEY: str({ default: '6ba154d4-e219-472a-9674-5fa5b1300ccf' }), - REACT_APP_CHAINFLIP_API_URL: url({ default: 'https://chainflip-broker.io' }), + REACT_APP_CHAINFLIP_API_KEY: str(), + REACT_APP_CHAINFLIP_API_URL: url(), } function reporter({ errors }: envalid.ReporterOptions) { From 2207d5b4029b06ebdaaac29550b260e5322c88c5 Mon Sep 17 00:00:00 2001 From: David Cumps Date: Wed, 23 Oct 2024 23:42:43 +0200 Subject: [PATCH 021/127] chore: newline eof --- .env.base | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.env.base b/.env.base index 2b321b22dbb..179eec72b9f 100644 --- a/.env.base +++ b/.env.base @@ -54,6 +54,7 @@ REACT_APP_ABSOLUTE_URL_PREFIX=https://app.shapeshift.com # Fetch UNI-V2 assets from Zapper REACT_APP_FEATURE_DYNAMIC_LP_ASSETS=false + # Fetch read-only assets from various providers (Zapper only for now) REACT_APP_FEATURE_READ_ONLY_ASSETS=true @@ -127,6 +128,7 @@ REACT_APP_MTPELERIN_INTEGRATION_KEY=954139b2-ef3e-4914-82ea-33192d3f43d3 REACT_APP_ONRAMPER_WIDGET_URL=https://buy.onramper.com/ REACT_APP_ONRAMPER_API_URL=https://api.onramper.com/ REACT_APP_ONRAMPER_API_KEY=pk_prod_01HWMA66BYRB2271G08XDZVVCX + # y.at REACT_APP_YAT_NODE_URL=https://a.y.at @@ -175,4 +177,4 @@ REACT_APP_ZRX_BASE_URL=https://api.proxy.shapeshift.com/api/v1/zrx/ # chainflip REACT_APP_CHAINFLIP_API_KEY=6ba154d4-e219-472a-9674-5fa5b1300ccf -REACT_APP_CHAINFLIP_API_URL=https://chainflip-broker.io \ No newline at end of file +REACT_APP_CHAINFLIP_API_URL=https://chainflip-broker.io From 56697f11c7130c2447c4c1f2efaaf139e2e204fe Mon Sep 17 00:00:00 2001 From: David Cumps Date: Wed, 23 Oct 2024 23:44:27 +0200 Subject: [PATCH 022/127] refactor: consistent order of swapper imports --- packages/swapper/src/constants.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/swapper/src/constants.ts b/packages/swapper/src/constants.ts index 14d4e5ab690..4f24513ce1d 100644 --- a/packages/swapper/src/constants.ts +++ b/packages/swapper/src/constants.ts @@ -1,15 +1,15 @@ import { assertUnreachable } from '@shapeshiftoss/utils' -import { arbitrumBridgeSwapper } from './swappers/ArbitrumBridgeSwapper/ArbitrumBridgeSwapper' import { arbitrumBridgeApi } from './swappers/ArbitrumBridgeSwapper/endpoints' +import { arbitrumBridgeSwapper } from './swappers/ArbitrumBridgeSwapper/ArbitrumBridgeSwapper' import { ARBITRUM_BRIDGE_SUPPORTED_CHAIN_IDS } from './swappers/ArbitrumBridgeSwapper/utils/constants' -import { CHAINFLIP_SUPPORTED_CHAIN_IDS } from './swappers/ChainflipSwapper/constants' import { chainflipApi } from './swappers/ChainflipSwapper/endpoints' import { chainflipSwapper } from './swappers/ChainflipSwapper/ChainflipSwapper' +import { CHAINFLIP_SUPPORTED_CHAIN_IDS } from './swappers/ChainflipSwapper/constants' -import { cowSwapper } from './swappers/CowSwapper/CowSwapper' import { cowApi } from './swappers/CowSwapper/endpoints' +import { cowSwapper } from './swappers/CowSwapper/CowSwapper' import { COW_SWAP_SUPPORTED_CHAIN_IDS } from './swappers/CowSwapper/utils/constants' import { lifiApi } from './swappers/LifiSwapper/endpoints' @@ -23,17 +23,17 @@ import { oneInchApi } from './swappers/OneInchSwapper/endpoints' import { oneInchSwapper } from './swappers/OneInchSwapper/OneInchSwapper' import { ONE_INCH_SUPPORTED_CHAIN_IDS } from './swappers/OneInchSwapper/utils/constants' -import { PORTALS_SUPPORTED_CHAIN_IDS } from './swappers/PortalsSwapper/constants' import { portalsApi } from './swappers/PortalsSwapper/endpoints' import { portalsSwapper } from './swappers/PortalsSwapper/PortalsSwapper' +import { PORTALS_SUPPORTED_CHAIN_IDS } from './swappers/PortalsSwapper/constants' -import { THORCHAIN_SUPPORTED_CHAIN_IDS } from './swappers/ThorchainSwapper/constants' import { thorchainApi } from './swappers/ThorchainSwapper/endpoints' import { thorchainSwapper } from './swappers/ThorchainSwapper/ThorchainSwapper' +import { THORCHAIN_SUPPORTED_CHAIN_IDS } from './swappers/ThorchainSwapper/constants' import { zrxApi } from './swappers/ZrxSwapper/endpoints' -import { ZRX_SUPPORTED_CHAIN_IDS } from './swappers/ZrxSwapper/utils/constants' import { zrxSwapper } from './swappers/ZrxSwapper/ZrxSwapper' +import { ZRX_SUPPORTED_CHAIN_IDS } from './swappers/ZrxSwapper/utils/constants' import type { SupportedChainIds, Swapper, SwapperApi } from './types' import { SwapperName } from './types' From 9507b737c6ff239026abd9d7168f4a98d4e932c5 Mon Sep 17 00:00:00 2001 From: David Cumps Date: Wed, 23 Oct 2024 23:50:14 +0200 Subject: [PATCH 023/127] fix: allowanceContract 0x0 --- packages/swapper/src/swappers/ChainflipSwapper/constants.ts | 2 +- packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts | 1 + .../ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/swapper/src/swappers/ChainflipSwapper/constants.ts b/packages/swapper/src/swappers/ChainflipSwapper/constants.ts index c63ccac3c22..0fd6193f347 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/constants.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/constants.ts @@ -50,4 +50,4 @@ export const usdcAsset: Asset = { precision: 6, relatedAssetKey: "eip155:1/erc20:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", symbol:"USDC" -} \ No newline at end of file +} diff --git a/packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts b/packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts index 480c179eda0..a7cb653f3c3 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts @@ -30,6 +30,7 @@ export const chainflipApi: SwapperApi = { buyTxHash: string | undefined message: string | [string, InterpolationOptions] | undefined }> => { + // TODO: Implement return { buyTxHash: undefined, status: TxStatus.Unknown, diff --git a/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts b/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts index afe7b6e3d67..1688724b62c 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts @@ -263,7 +263,7 @@ export const getChainflipTradeQuote = async ( buyAsset: buyAsset, sellAsset: sellAsset, accountNumber: 0, - allowanceContract: "", + allowanceContract: "0x0", // Chainflip does not use contracts estimatedExecutionTimeMs: singleQuoteResponse.estimatedDurationSeconds! * 1000 } ] From 668856f543fc0ce69304a9272ec9b9e69a1570b3 Mon Sep 17 00:00:00 2001 From: David Cumps Date: Wed, 23 Oct 2024 23:54:57 +0200 Subject: [PATCH 024/127] feat: filter out assets even more --- .../ChainflipSwapper/ChainflipSwapper.ts | 3 ++ .../getChainflipTradeQuote/getTradeQuote.ts | 33 +++++++++++-------- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/packages/swapper/src/swappers/ChainflipSwapper/ChainflipSwapper.ts b/packages/swapper/src/swappers/ChainflipSwapper/ChainflipSwapper.ts index 634270f553f..9455babe838 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/ChainflipSwapper.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/ChainflipSwapper.ts @@ -3,12 +3,14 @@ import type { Asset } from '@shapeshiftoss/types' import type { BuyAssetBySellIdInput, Swapper } from '../../types' import { CHAINFLIP_SUPPORTED_CHAIN_IDS } from './constants' +import { isSupportedAsset } from "./utils/helpers"; export const chainflipSwapper: Swapper = { filterAssetIdsBySellable: (assets: Asset[]): Promise => { return Promise.resolve( assets .filter(asset => CHAINFLIP_SUPPORTED_CHAIN_IDS.sell.includes(asset.chainId)) + .filter(asset => isSupportedAsset(asset.chainId, asset.symbol)) .map(asset => asset.assetId), ) }, @@ -17,6 +19,7 @@ export const chainflipSwapper: Swapper = { return Promise.resolve( input.assets .filter(asset => CHAINFLIP_SUPPORTED_CHAIN_IDS.buy.includes(asset.chainId)) + .filter(asset => isSupportedAsset(asset.chainId, asset.symbol)) .map(asset => asset.assetId), ) }, diff --git a/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts b/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts index 1688724b62c..c8c284ad4a0 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts @@ -1,30 +1,33 @@ -import { v4 as uuid } from "uuid"; -import { Err, Ok, Result } from "@sniptt/monads"; -import { KnownChainIds } from "@shapeshiftoss/types"; -import { AssetId, CHAIN_NAMESPACE, fromAssetId } from "@shapeshiftoss/caip"; +import {v4 as uuid} from "uuid"; +import {Err, Ok, Result} from "@sniptt/monads"; +import {KnownChainIds} from "@shapeshiftoss/types"; +import {AssetId, CHAIN_NAMESPACE, fromAssetId} from "@shapeshiftoss/caip"; import { type GetEvmTradeQuoteInput, - GetTradeQuoteInput, type ProtocolFee, + GetTradeQuoteInput, + type ProtocolFee, SwapErrorRight, SwapperDeps, + SwapperName, TradeQuote, TradeQuoteError } from "../../../types"; -import { getRate, makeSwapErrorRight } from "../../../utils"; +import {getRate, makeSwapErrorRight} from "../../../utils"; import { - CHAINFLIP_SWAP_SOURCE, CHAINFLIP_BOOST_SWAP_SOURCE, - CHAINFLIP_DCA_SWAP_SOURCE, CHAINFLIP_DCA_BOOST_SWAP_SOURCE, + CHAINFLIP_DCA_SWAP_SOURCE, + CHAINFLIP_SWAP_SOURCE, chainIdToChainflipNetwork, usdcAsset } from "../constants"; -import { isSupportedChainId, isSupportedAsset } from "../utils/helpers"; -import { chainflipService } from "../utils/chainflipService"; -import { ChainflipBaasQuoteQuote, ChainflipBaasQuoteQuoteFee } from "../models"; -import { getEvmTxFees } from "../txFeeHelpers/evmTxFees/getEvmTxFees"; +import {isSupportedAsset, isSupportedChainId} from "../utils/helpers"; +import {chainflipService} from "../utils/chainflipService"; +import {ChainflipBaasQuoteQuote, ChainflipBaasQuoteQuoteFee} from "../models"; +import {getEvmTxFees} from "../txFeeHelpers/evmTxFees/getEvmTxFees"; +import {getDefaultSlippageDecimalPercentageForSwapper} from "../../../constants"; // import { getUtxoTxFees } from "../txFeeHelpers/utxoTxFees/getUtxoTxFees"; export const getChainflipTradeQuote = async ( @@ -105,6 +108,8 @@ export const getChainflipTradeQuote = async ( const { data: quoteResponse } = maybeQuoteResponse.unwrap() + const defaultSlippage = getDefaultSlippageDecimalPercentageForSwapper(SwapperName.Chainflip); + const getGasFee = async () => { const { chainNamespace } = fromAssetId(sellAsset.assetId); @@ -206,7 +211,7 @@ export const getChainflipTradeQuote = async ( potentialAffiliateBps: commissionBps, affiliateBps: commissionBps, isStreaming: isStreaming, - slippageTolerancePercentageDecimal: undefined, + slippageTolerancePercentageDecimal: defaultSlippage, steps: [ { buyAmountBeforeFeesCryptoBaseUnit: singleQuoteResponse.boostQuote.egressAmountNative!, @@ -248,7 +253,7 @@ export const getChainflipTradeQuote = async ( potentialAffiliateBps: commissionBps, affiliateBps: commissionBps, isStreaming: isStreaming, - slippageTolerancePercentageDecimal: undefined, + slippageTolerancePercentageDecimal: defaultSlippage, steps: [ { buyAmountBeforeFeesCryptoBaseUnit: singleQuoteResponse.egressAmountNative!, From 1765b867ed6d5f0f7b3563700ac40e551c0c0a45 Mon Sep 17 00:00:00 2001 From: David Cumps Date: Thu, 24 Oct 2024 00:16:32 +0200 Subject: [PATCH 025/127] feat: provide gaslimits for simple asset sends --- .../swapper/src/swappers/ChainflipSwapper/constants.ts | 9 +++++++++ .../getChainflipTradeQuote/getTradeQuote.ts | 1 + .../txFeeHelpers/evmTxFees/getEvmTxFees.ts | 8 ++++++-- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/packages/swapper/src/swappers/ChainflipSwapper/constants.ts b/packages/swapper/src/swappers/ChainflipSwapper/constants.ts index 0fd6193f347..07be8358fdf 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/constants.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/constants.ts @@ -28,6 +28,15 @@ export const chainIdToChainflipNetwork: Partial> = // TODO: Add Polkadot } +export const assetGasLimits: Partial> = { + ["eth.eth"]: '34000', + ["flip.eth"]: '52000', + ["usdc.eth"]: '63000', + ["usdt.eth"]: '70000', + ["eth.arb"]: '100000', + ["usdc.arb"]: '100000', +} + export const CHAINFLIP_SUPPORTED_CHAIN_IDS: SupportedChainIds = { sell: ChainflipSupportedChainIds as unknown as ChainId[], buy: ChainflipSupportedChainIds as unknown as ChainId[], diff --git a/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts b/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts index c8c284ad4a0..383563b07ae 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts @@ -119,6 +119,7 @@ export const getChainflipTradeQuote = async ( return await getEvmTxFees({ adapter: sellAdapter, supportsEIP1559: (input as GetEvmTradeQuoteInput).supportsEIP1559, + sendAsset: sellChainflipChainKey }); } diff --git a/packages/swapper/src/swappers/ChainflipSwapper/txFeeHelpers/evmTxFees/getEvmTxFees.ts b/packages/swapper/src/swappers/ChainflipSwapper/txFeeHelpers/evmTxFees/getEvmTxFees.ts index 7f45affa02d..127bc4cf38f 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/txFeeHelpers/evmTxFees/getEvmTxFees.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/txFeeHelpers/evmTxFees/getEvmTxFees.ts @@ -1,9 +1,11 @@ import type { EvmChainAdapter } from '@shapeshiftoss/chain-adapters' import { evm } from '@shapeshiftoss/chain-adapters' +import { assetGasLimits } from "../../constants"; type GetEvmTxFeesArgs = { adapter: EvmChainAdapter - supportsEIP1559: boolean + supportsEIP1559: boolean, + sendAsset: string } export const getEvmTxFees = async (args: GetEvmTxFeesArgs): Promise => { @@ -11,9 +13,11 @@ export const getEvmTxFees = async (args: GetEvmTxFeesArgs): Promise => { const { average } = await adapter.getGasFeeData() + const gasLimit = (args.sendAsset in assetGasLimits) ? assetGasLimits[args.sendAsset]! : "100000"; + return evm.calcNetworkFeeCryptoBaseUnit({ ...average, supportsEIP1559, - gasLimit: "100000", // TODO: Get gas limits based on ingress coins + gasLimit }) } From 7b3cc2671b7af567171775065edc61a987b84b5b Mon Sep 17 00:00:00 2001 From: David Cumps Date: Thu, 24 Oct 2024 00:19:02 +0200 Subject: [PATCH 026/127] chore: newline at eof --- packages/swapper/src/swappers/ChainflipSwapper/utils/helpers.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/swapper/src/swappers/ChainflipSwapper/utils/helpers.ts b/packages/swapper/src/swappers/ChainflipSwapper/utils/helpers.ts index 88a36236ab0..7828ae59923 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/utils/helpers.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/utils/helpers.ts @@ -9,4 +9,4 @@ export const isSupportedChainId = (chainId: ChainId): chainId is ChainflipSuppor export const isSupportedAsset = (chainId: ChainId, symbol: string): chainId is ChainflipSupportedChainId => { return ChainflipSupportedAssets[chainId as ChainflipSupportedChainId].includes(symbol.toLowerCase()) -} \ No newline at end of file +} From a6d42f99cf11136b41cc64b420f419ae843f6ccd Mon Sep 17 00:00:00 2001 From: David Cumps Date: Thu, 24 Oct 2024 00:57:01 +0200 Subject: [PATCH 027/127] feat: support amount to low --- .../getChainflipTradeQuote/getTradeQuote.ts | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts b/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts index 383563b07ae..b8d6ab1eb38 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts @@ -28,6 +28,7 @@ import {chainflipService} from "../utils/chainflipService"; import {ChainflipBaasQuoteQuote, ChainflipBaasQuoteQuoteFee} from "../models"; import {getEvmTxFees} from "../txFeeHelpers/evmTxFees/getEvmTxFees"; import {getDefaultSlippageDecimalPercentageForSwapper} from "../../../constants"; +import {AxiosError} from "axios"; // import { getUtxoTxFees } from "../txFeeHelpers/utxoTxFees/getUtxoTxFees"; export const getChainflipTradeQuote = async ( @@ -96,8 +97,19 @@ export const getChainflipTradeQuote = async ( `${brokerUrl}/quotes-native?apiKey=${apiKey}&sourceAsset=${sellChainflipChainKey}&destinationAsset=${buyChainflipChainKey}&amount=${sellAmount}&commissionBps=${serviceCommission}`, ); - // TODO: Throw SellAmountBelowMinimum if that's the cause (parse error response) if (maybeQuoteResponse.isErr()) { + const error = maybeQuoteResponse.unwrapErr(); + const cause = error.cause as AxiosError; + + if (cause.message.includes("code 400") && cause.response!.data.detail.includes("Amount outside asset bounds")) { + return Err( + makeSwapErrorRight({ + message: cause.response!.data.detail, + code: TradeQuoteError.SellAmountBelowMinimum, + }), + ) + } + return Err( makeSwapErrorRight({ message: 'Quote request failed', From dfa6a3a1f8440927704a8246c45fad1360f13aa4 Mon Sep 17 00:00:00 2001 From: David Cumps Date: Thu, 24 Oct 2024 01:00:51 +0200 Subject: [PATCH 028/127] refactor: delete unneeded generated openai models --- .../models/ChainflipBaasAssetsAssetInfo.ts | 169 ------------------ .../ChainflipBaasAssetsAssetsResponse.ts | 72 -------- .../ChainflipBaasBalanceBalanceResponse.ts | 72 -------- .../models/ChainflipBaasFeesFeesResponse.ts | 72 -------- .../ChainflipBaasNetworksNetworkInfo.ts | 79 -------- .../ChainflipBaasNetworksNetworksResponse.ts | 72 -------- .../models/ChainflipBaasRpcRpcRequest.ts | 104 ----------- .../ChainflipBaasSwapAdvancedSwapRequest.ts | 73 -------- .../models/ChainflipBaasSwapCcmRequest.ts | 76 -------- .../MicrosoftAspNetCoreMvcProblemDetails.ts | 101 ----------- ...ftAspNetCoreMvcValidationProblemDetails.ts | 109 ----------- .../swappers/ChainflipSwapper/models/index.ts | 12 -- 12 files changed, 1011 deletions(-) delete mode 100644 packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasAssetsAssetInfo.ts delete mode 100644 packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasAssetsAssetsResponse.ts delete mode 100644 packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasBalanceBalanceResponse.ts delete mode 100644 packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasFeesFeesResponse.ts delete mode 100644 packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasNetworksNetworkInfo.ts delete mode 100644 packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasNetworksNetworksResponse.ts delete mode 100644 packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasRpcRpcRequest.ts delete mode 100644 packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasSwapAdvancedSwapRequest.ts delete mode 100644 packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasSwapCcmRequest.ts delete mode 100644 packages/swapper/src/swappers/ChainflipSwapper/models/MicrosoftAspNetCoreMvcProblemDetails.ts delete mode 100644 packages/swapper/src/swappers/ChainflipSwapper/models/MicrosoftAspNetCoreMvcValidationProblemDetails.ts diff --git a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasAssetsAssetInfo.ts b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasAssetsAssetInfo.ts deleted file mode 100644 index 92027e8fd91..00000000000 --- a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasAssetsAssetInfo.ts +++ /dev/null @@ -1,169 +0,0 @@ -// @ts-nocheck -/* tslint:disable */ -/* eslint-disable */ -/** - * Chainflip Broker as a Service - * Run your own Chainflip Broker without any hassle. - * - * The version of the OpenAPI document: v1 - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - -import { exists, mapValues } from '../runtime'; -/** - * - * @export - * @interface ChainflipBaasAssetsAssetInfo - */ -export interface ChainflipBaasAssetsAssetInfo { - /** - * Unique id of the asset. - * @type {string} - * @memberof ChainflipBaasAssetsAssetInfo - */ - id?: string; - /** - * Direction an asset can be used in. Ingress assets can only be used to swap from. Egress assets can only be used to swap to. Assets with both can be used to swap from and to. - * @type {string} - * @memberof ChainflipBaasAssetsAssetInfo - */ - direction?: ChainflipBaasAssetsAssetInfoDirectionEnum; - /** - * Display ticker of the asset. - * @type {string} - * @memberof ChainflipBaasAssetsAssetInfo - */ - ticker?: string; - /** - * Descriptive name of the asset. - * @type {string} - * @memberof ChainflipBaasAssetsAssetInfo - */ - name?: string; - /** - * Name of the network where the asset is located. - * @type {string} - * @memberof ChainflipBaasAssetsAssetInfo - */ - network?: string; - /** - * The contract address for tokens which have one. - * @type {string} - * @memberof ChainflipBaasAssetsAssetInfo - */ - contractAddress?: string | null; - /** - * A url to the logo for the network. - * @type {string} - * @memberof ChainflipBaasAssetsAssetInfo - */ - readonly networkLogo?: string; - /** - * A url to the logo for the asset. - * @type {string} - * @memberof ChainflipBaasAssetsAssetInfo - */ - readonly assetLogo?: string; - /** - * Number of decimals the asset native value contains. - * @type {number} - * @memberof ChainflipBaasAssetsAssetInfo - */ - decimals?: number; - /** - * Minimum amount required to swap the asset. - * @type {number} - * @memberof ChainflipBaasAssetsAssetInfo - */ - minimalAmount?: number; - /** - * Minimum amount in native units required to swap the asset. - * @type {string} - * @memberof ChainflipBaasAssetsAssetInfo - */ - readonly minimalAmountNative?: string; - /** - * Current pool price of the asset in USDC. - * @type {number} - * @memberof ChainflipBaasAssetsAssetInfo - */ - readonly usdPrice?: number | null; - /** - * Current pool price of the asset in USDC native units. - * @type {string} - * @memberof ChainflipBaasAssetsAssetInfo - */ - readonly usdPriceNative?: string | null; -} - - -/** - * @export - */ -export const ChainflipBaasAssetsAssetInfoDirectionEnum = { - Ingress: 'ingress', - Egress: 'egress', - Both: 'both' -} as const; -export type ChainflipBaasAssetsAssetInfoDirectionEnum = typeof ChainflipBaasAssetsAssetInfoDirectionEnum[keyof typeof ChainflipBaasAssetsAssetInfoDirectionEnum]; - - -/** - * Check if a given object implements the ChainflipBaasAssetsAssetInfo interface. - */ -export function instanceOfChainflipBaasAssetsAssetInfo(value: object): boolean { - let isInstance = true; - - return isInstance; -} - -export function ChainflipBaasAssetsAssetInfoFromJSON(json: any): ChainflipBaasAssetsAssetInfo { - return ChainflipBaasAssetsAssetInfoFromJSONTyped(json, false); -} - -export function ChainflipBaasAssetsAssetInfoFromJSONTyped(json: any, ignoreDiscriminator: boolean): ChainflipBaasAssetsAssetInfo { - if ((json === undefined) || (json === null)) { - return json; - } - return { - - 'id': !exists(json, 'id') ? undefined : json['id'], - 'direction': !exists(json, 'direction') ? undefined : json['direction'], - 'ticker': !exists(json, 'ticker') ? undefined : json['ticker'], - 'name': !exists(json, 'name') ? undefined : json['name'], - 'network': !exists(json, 'network') ? undefined : json['network'], - 'contractAddress': !exists(json, 'contractAddress') ? undefined : json['contractAddress'], - 'networkLogo': !exists(json, 'networkLogo') ? undefined : json['networkLogo'], - 'assetLogo': !exists(json, 'assetLogo') ? undefined : json['assetLogo'], - 'decimals': !exists(json, 'decimals') ? undefined : json['decimals'], - 'minimalAmount': !exists(json, 'minimalAmount') ? undefined : json['minimalAmount'], - 'minimalAmountNative': !exists(json, 'minimalAmountNative') ? undefined : json['minimalAmountNative'], - 'usdPrice': !exists(json, 'usdPrice') ? undefined : json['usdPrice'], - 'usdPriceNative': !exists(json, 'usdPriceNative') ? undefined : json['usdPriceNative'], - }; -} - -export function ChainflipBaasAssetsAssetInfoToJSON(value?: ChainflipBaasAssetsAssetInfo | null): any { - if (value === undefined) { - return undefined; - } - if (value === null) { - return null; - } - return { - - 'id': value.id, - 'direction': value.direction, - 'ticker': value.ticker, - 'name': value.name, - 'network': value.network, - 'contractAddress': value.contractAddress, - 'decimals': value.decimals, - 'minimalAmount': value.minimalAmount, - }; -} - diff --git a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasAssetsAssetsResponse.ts b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasAssetsAssetsResponse.ts deleted file mode 100644 index 59a0cd2ccc4..00000000000 --- a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasAssetsAssetsResponse.ts +++ /dev/null @@ -1,72 +0,0 @@ -// @ts-nocheck -/* tslint:disable */ -/* eslint-disable */ -/** - * Chainflip Broker as a Service - * Run your own Chainflip Broker without any hassle. - * - * The version of the OpenAPI document: v1 - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - -import { exists, mapValues } from '../runtime'; -import type { ChainflipBaasAssetsAssetInfo } from './ChainflipBaasAssetsAssetInfo'; -import { - ChainflipBaasAssetsAssetInfoFromJSON, - ChainflipBaasAssetsAssetInfoFromJSONTyped, - ChainflipBaasAssetsAssetInfoToJSON, -} from './ChainflipBaasAssetsAssetInfo'; - -/** - * - * @export - * @interface ChainflipBaasAssetsAssetsResponse - */ -export interface ChainflipBaasAssetsAssetsResponse { - /** - * All available assets. - * @type {Array} - * @memberof ChainflipBaasAssetsAssetsResponse - */ - readonly assets?: Array; -} - -/** - * Check if a given object implements the ChainflipBaasAssetsAssetsResponse interface. - */ -export function instanceOfChainflipBaasAssetsAssetsResponse(value: object): boolean { - let isInstance = true; - - return isInstance; -} - -export function ChainflipBaasAssetsAssetsResponseFromJSON(json: any): ChainflipBaasAssetsAssetsResponse { - return ChainflipBaasAssetsAssetsResponseFromJSONTyped(json, false); -} - -export function ChainflipBaasAssetsAssetsResponseFromJSONTyped(json: any, ignoreDiscriminator: boolean): ChainflipBaasAssetsAssetsResponse { - if ((json === undefined) || (json === null)) { - return json; - } - return { - - 'assets': !exists(json, 'assets') ? undefined : ((json['assets'] as Array).map(ChainflipBaasAssetsAssetInfoFromJSON)), - }; -} - -export function ChainflipBaasAssetsAssetsResponseToJSON(value?: ChainflipBaasAssetsAssetsResponse | null): any { - if (value === undefined) { - return undefined; - } - if (value === null) { - return null; - } - return { - - }; -} - diff --git a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasBalanceBalanceResponse.ts b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasBalanceBalanceResponse.ts deleted file mode 100644 index 4fad00479ff..00000000000 --- a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasBalanceBalanceResponse.ts +++ /dev/null @@ -1,72 +0,0 @@ -// @ts-nocheck -/* tslint:disable */ -/* eslint-disable */ -/** - * Chainflip Broker as a Service - * Run your own Chainflip Broker without any hassle. - * - * The version of the OpenAPI document: v1 - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - -import { exists, mapValues } from '../runtime'; -/** - * - * @export - * @interface ChainflipBaasBalanceBalanceResponse - */ -export interface ChainflipBaasBalanceBalanceResponse { - /** - * Current FLIP balance - * @type {number} - * @memberof ChainflipBaasBalanceBalanceResponse - */ - readonly currentBalance?: number; - /** - * Current FLIP balance in flipperinos. - * @type {string} - * @memberof ChainflipBaasBalanceBalanceResponse - */ - readonly currentBalanceNative?: string; -} - -/** - * Check if a given object implements the ChainflipBaasBalanceBalanceResponse interface. - */ -export function instanceOfChainflipBaasBalanceBalanceResponse(value: object): boolean { - let isInstance = true; - - return isInstance; -} - -export function ChainflipBaasBalanceBalanceResponseFromJSON(json: any): ChainflipBaasBalanceBalanceResponse { - return ChainflipBaasBalanceBalanceResponseFromJSONTyped(json, false); -} - -export function ChainflipBaasBalanceBalanceResponseFromJSONTyped(json: any, ignoreDiscriminator: boolean): ChainflipBaasBalanceBalanceResponse { - if ((json === undefined) || (json === null)) { - return json; - } - return { - - 'currentBalance': !exists(json, 'currentBalance') ? undefined : json['currentBalance'], - 'currentBalanceNative': !exists(json, 'currentBalanceNative') ? undefined : json['currentBalanceNative'], - }; -} - -export function ChainflipBaasBalanceBalanceResponseToJSON(value?: ChainflipBaasBalanceBalanceResponse | null): any { - if (value === undefined) { - return undefined; - } - if (value === null) { - return null; - } - return { - - }; -} - diff --git a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasFeesFeesResponse.ts b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasFeesFeesResponse.ts deleted file mode 100644 index 7fde4c1d0bb..00000000000 --- a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasFeesFeesResponse.ts +++ /dev/null @@ -1,72 +0,0 @@ -// @ts-nocheck -/* tslint:disable */ -/* eslint-disable */ -/** - * Chainflip Broker as a Service - * Run your own Chainflip Broker without any hassle. - * - * The version of the OpenAPI document: v1 - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - -import { exists, mapValues } from '../runtime'; -/** - * - * @export - * @interface ChainflipBaasFeesFeesResponse - */ -export interface ChainflipBaasFeesFeesResponse { - /** - * Earned broker fees per asset. - * @type {{ [key: string]: number; }} - * @memberof ChainflipBaasFeesFeesResponse - */ - readonly earnedFees?: { [key: string]: number; }; - /** - * Earned broker fees per asset in native units. - * @type {{ [key: string]: string; }} - * @memberof ChainflipBaasFeesFeesResponse - */ - readonly earnedFeesNative?: { [key: string]: string; }; -} - -/** - * Check if a given object implements the ChainflipBaasFeesFeesResponse interface. - */ -export function instanceOfChainflipBaasFeesFeesResponse(value: object): boolean { - let isInstance = true; - - return isInstance; -} - -export function ChainflipBaasFeesFeesResponseFromJSON(json: any): ChainflipBaasFeesFeesResponse { - return ChainflipBaasFeesFeesResponseFromJSONTyped(json, false); -} - -export function ChainflipBaasFeesFeesResponseFromJSONTyped(json: any, ignoreDiscriminator: boolean): ChainflipBaasFeesFeesResponse { - if ((json === undefined) || (json === null)) { - return json; - } - return { - - 'earnedFees': !exists(json, 'earnedFees') ? undefined : json['earnedFees'], - 'earnedFeesNative': !exists(json, 'earnedFeesNative') ? undefined : json['earnedFeesNative'], - }; -} - -export function ChainflipBaasFeesFeesResponseToJSON(value?: ChainflipBaasFeesFeesResponse | null): any { - if (value === undefined) { - return undefined; - } - if (value === null) { - return null; - } - return { - - }; -} - diff --git a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasNetworksNetworkInfo.ts b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasNetworksNetworkInfo.ts deleted file mode 100644 index 0a3d88925da..00000000000 --- a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasNetworksNetworkInfo.ts +++ /dev/null @@ -1,79 +0,0 @@ -// @ts-nocheck -/* tslint:disable */ -/* eslint-disable */ -/** - * Chainflip Broker as a Service - * Run your own Chainflip Broker without any hassle. - * - * The version of the OpenAPI document: v1 - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - -import { exists, mapValues } from '../runtime'; -/** - * - * @export - * @interface ChainflipBaasNetworksNetworkInfo - */ -export interface ChainflipBaasNetworksNetworkInfo { - /** - * Network id. - * @type {string} - * @memberof ChainflipBaasNetworksNetworkInfo - */ - readonly id?: string; - /** - * Network name. - * @type {string} - * @memberof ChainflipBaasNetworksNetworkInfo - */ - readonly name?: string; - /** - * A url to the logo for the network. - * @type {string} - * @memberof ChainflipBaasNetworksNetworkInfo - */ - readonly logo?: string; -} - -/** - * Check if a given object implements the ChainflipBaasNetworksNetworkInfo interface. - */ -export function instanceOfChainflipBaasNetworksNetworkInfo(value: object): boolean { - let isInstance = true; - - return isInstance; -} - -export function ChainflipBaasNetworksNetworkInfoFromJSON(json: any): ChainflipBaasNetworksNetworkInfo { - return ChainflipBaasNetworksNetworkInfoFromJSONTyped(json, false); -} - -export function ChainflipBaasNetworksNetworkInfoFromJSONTyped(json: any, ignoreDiscriminator: boolean): ChainflipBaasNetworksNetworkInfo { - if ((json === undefined) || (json === null)) { - return json; - } - return { - - 'id': !exists(json, 'id') ? undefined : json['id'], - 'name': !exists(json, 'name') ? undefined : json['name'], - 'logo': !exists(json, 'logo') ? undefined : json['logo'], - }; -} - -export function ChainflipBaasNetworksNetworkInfoToJSON(value?: ChainflipBaasNetworksNetworkInfo | null): any { - if (value === undefined) { - return undefined; - } - if (value === null) { - return null; - } - return { - - }; -} - diff --git a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasNetworksNetworksResponse.ts b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasNetworksNetworksResponse.ts deleted file mode 100644 index 87c7b21dc7f..00000000000 --- a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasNetworksNetworksResponse.ts +++ /dev/null @@ -1,72 +0,0 @@ -// @ts-nocheck -/* tslint:disable */ -/* eslint-disable */ -/** - * Chainflip Broker as a Service - * Run your own Chainflip Broker without any hassle. - * - * The version of the OpenAPI document: v1 - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - -import { exists, mapValues } from '../runtime'; -import type { ChainflipBaasNetworksNetworkInfo } from './ChainflipBaasNetworksNetworkInfo'; -import { - ChainflipBaasNetworksNetworkInfoFromJSON, - ChainflipBaasNetworksNetworkInfoFromJSONTyped, - ChainflipBaasNetworksNetworkInfoToJSON, -} from './ChainflipBaasNetworksNetworkInfo'; - -/** - * - * @export - * @interface ChainflipBaasNetworksNetworksResponse - */ -export interface ChainflipBaasNetworksNetworksResponse { - /** - * All available networks. - * @type {Array} - * @memberof ChainflipBaasNetworksNetworksResponse - */ - readonly networks?: Array; -} - -/** - * Check if a given object implements the ChainflipBaasNetworksNetworksResponse interface. - */ -export function instanceOfChainflipBaasNetworksNetworksResponse(value: object): boolean { - let isInstance = true; - - return isInstance; -} - -export function ChainflipBaasNetworksNetworksResponseFromJSON(json: any): ChainflipBaasNetworksNetworksResponse { - return ChainflipBaasNetworksNetworksResponseFromJSONTyped(json, false); -} - -export function ChainflipBaasNetworksNetworksResponseFromJSONTyped(json: any, ignoreDiscriminator: boolean): ChainflipBaasNetworksNetworksResponse { - if ((json === undefined) || (json === null)) { - return json; - } - return { - - 'networks': !exists(json, 'networks') ? undefined : ((json['networks'] as Array).map(ChainflipBaasNetworksNetworkInfoFromJSON)), - }; -} - -export function ChainflipBaasNetworksNetworksResponseToJSON(value?: ChainflipBaasNetworksNetworksResponse | null): any { - if (value === undefined) { - return undefined; - } - if (value === null) { - return null; - } - return { - - }; -} - diff --git a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasRpcRpcRequest.ts b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasRpcRpcRequest.ts deleted file mode 100644 index e05ed6dea0e..00000000000 --- a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasRpcRpcRequest.ts +++ /dev/null @@ -1,104 +0,0 @@ -// @ts-nocheck -/* tslint:disable */ -/* eslint-disable */ -/** - * Chainflip Broker as a Service - * Run your own Chainflip Broker without any hassle. - * - * The version of the OpenAPI document: v1 - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - -import { exists, mapValues } from '../runtime'; -/** - * - * @export - * @interface ChainflipBaasRpcRpcRequest - */ -export interface ChainflipBaasRpcRpcRequest { - /** - * Hardcode "1" - * @type {number} - * @memberof ChainflipBaasRpcRpcRequest - */ - id: number; - /** - * Hardcode "2.0" - * @type {string} - * @memberof ChainflipBaasRpcRpcRequest - */ - jsonrpc: string; - /** - * Hardcode "broker_request_swap_deposit_address" - * @type {string} - * @memberof ChainflipBaasRpcRpcRequest - */ - method: string; - /** - * source_asset: Source asset. - * - * destination_asset: Egress asset. - * - * destination_address: Egress Address. - * - * broker_commission: Will be ignored and configured partner commission will be used. - * - * channel_metadata: (Optional) Cross-chain message metadata as a JSON object: {"gas_budget": <amount>, "message":<hex_string>, "cf_parameters": <hex_string>}. Where message and cf_parameters are hex encoded strings. - * - * boost_fee: (Optional) Maximum accepted boost fee in basis points (100th of a percent). - * @type {Array} - * @memberof ChainflipBaasRpcRpcRequest - */ - params: Array; -} - -/** - * Check if a given object implements the ChainflipBaasRpcRpcRequest interface. - */ -export function instanceOfChainflipBaasRpcRpcRequest(value: object): boolean { - let isInstance = true; - isInstance = isInstance && "id" in value; - isInstance = isInstance && "jsonrpc" in value; - isInstance = isInstance && "method" in value; - isInstance = isInstance && "params" in value; - - return isInstance; -} - -export function ChainflipBaasRpcRpcRequestFromJSON(json: any): ChainflipBaasRpcRpcRequest { - return ChainflipBaasRpcRpcRequestFromJSONTyped(json, false); -} - -export function ChainflipBaasRpcRpcRequestFromJSONTyped(json: any, ignoreDiscriminator: boolean): ChainflipBaasRpcRpcRequest { - if ((json === undefined) || (json === null)) { - return json; - } - return { - - 'id': json['id'], - 'jsonrpc': json['jsonrpc'], - 'method': json['method'], - 'params': json['params'], - }; -} - -export function ChainflipBaasRpcRpcRequestToJSON(value?: ChainflipBaasRpcRpcRequest | null): any { - if (value === undefined) { - return undefined; - } - if (value === null) { - return null; - } - return { - - 'id': value.id, - 'jsonrpc': value.jsonrpc, - 'method': value.method, - 'params': value.params, - }; -} - diff --git a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasSwapAdvancedSwapRequest.ts b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasSwapAdvancedSwapRequest.ts deleted file mode 100644 index e14fa34be2e..00000000000 --- a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasSwapAdvancedSwapRequest.ts +++ /dev/null @@ -1,73 +0,0 @@ -// @ts-nocheck -/* tslint:disable */ -/* eslint-disable */ -/** - * Chainflip Broker as a Service - * Run your own Chainflip Broker without any hassle. - * - * The version of the OpenAPI document: v1 - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - -import { exists, mapValues } from '../runtime'; -import type { ChainflipBaasSwapCcmRequest } from './ChainflipBaasSwapCcmRequest'; -import { - ChainflipBaasSwapCcmRequestFromJSON, - ChainflipBaasSwapCcmRequestFromJSONTyped, - ChainflipBaasSwapCcmRequestToJSON, -} from './ChainflipBaasSwapCcmRequest'; - -/** - * - * @export - * @interface ChainflipBaasSwapAdvancedSwapRequest - */ -export interface ChainflipBaasSwapAdvancedSwapRequest { - /** - * - * @type {ChainflipBaasSwapCcmRequest} - * @memberof ChainflipBaasSwapAdvancedSwapRequest - */ - ccmPayload?: ChainflipBaasSwapCcmRequest; -} - -/** - * Check if a given object implements the ChainflipBaasSwapAdvancedSwapRequest interface. - */ -export function instanceOfChainflipBaasSwapAdvancedSwapRequest(value: object): boolean { - let isInstance = true; - - return isInstance; -} - -export function ChainflipBaasSwapAdvancedSwapRequestFromJSON(json: any): ChainflipBaasSwapAdvancedSwapRequest { - return ChainflipBaasSwapAdvancedSwapRequestFromJSONTyped(json, false); -} - -export function ChainflipBaasSwapAdvancedSwapRequestFromJSONTyped(json: any, ignoreDiscriminator: boolean): ChainflipBaasSwapAdvancedSwapRequest { - if ((json === undefined) || (json === null)) { - return json; - } - return { - - 'ccmPayload': !exists(json, 'ccmPayload') ? undefined : ChainflipBaasSwapCcmRequestFromJSON(json['ccmPayload']), - }; -} - -export function ChainflipBaasSwapAdvancedSwapRequestToJSON(value?: ChainflipBaasSwapAdvancedSwapRequest | null): any { - if (value === undefined) { - return undefined; - } - if (value === null) { - return null; - } - return { - - 'ccmPayload': ChainflipBaasSwapCcmRequestToJSON(value.ccmPayload), - }; -} - diff --git a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasSwapCcmRequest.ts b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasSwapCcmRequest.ts deleted file mode 100644 index ebab52a8947..00000000000 --- a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasSwapCcmRequest.ts +++ /dev/null @@ -1,76 +0,0 @@ -// @ts-nocheck -/* tslint:disable */ -/* eslint-disable */ -/** - * Chainflip Broker as a Service - * Run your own Chainflip Broker without any hassle. - * - * The version of the OpenAPI document: v1 - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - -import { exists, mapValues } from '../runtime'; -/** - * Cross-Chain Messaging payload. More details can be found at https://docs.chainflip.io/swapping/integrations/advanced/cross-chain-messaging/cross-chain-messaging - * @export - * @interface ChainflipBaasSwapCcmRequest - */ -export interface ChainflipBaasSwapCcmRequest { - /** - * Gas budget for the call on the destination chain. This amount is based on the source asset and will be subtracted from the input amount and swapped to pay for gas. - * @type {string} - * @memberof ChainflipBaasSwapCcmRequest - */ - gasBudget: string; - /** - * Hex-encoded message that is passed to the destination address on the destination chain. The message should be shorter than 10k bytes. - * @type {string} - * @memberof ChainflipBaasSwapCcmRequest - */ - message: string; -} - -/** - * Check if a given object implements the ChainflipBaasSwapCcmRequest interface. - */ -export function instanceOfChainflipBaasSwapCcmRequest(value: object): boolean { - let isInstance = true; - isInstance = isInstance && "gasBudget" in value; - isInstance = isInstance && "message" in value; - - return isInstance; -} - -export function ChainflipBaasSwapCcmRequestFromJSON(json: any): ChainflipBaasSwapCcmRequest { - return ChainflipBaasSwapCcmRequestFromJSONTyped(json, false); -} - -export function ChainflipBaasSwapCcmRequestFromJSONTyped(json: any, ignoreDiscriminator: boolean): ChainflipBaasSwapCcmRequest { - if ((json === undefined) || (json === null)) { - return json; - } - return { - - 'gasBudget': json['gas_budget'], - 'message': json['message'], - }; -} - -export function ChainflipBaasSwapCcmRequestToJSON(value?: ChainflipBaasSwapCcmRequest | null): any { - if (value === undefined) { - return undefined; - } - if (value === null) { - return null; - } - return { - - 'gas_budget': value.gasBudget, - 'message': value.message, - }; -} - diff --git a/packages/swapper/src/swappers/ChainflipSwapper/models/MicrosoftAspNetCoreMvcProblemDetails.ts b/packages/swapper/src/swappers/ChainflipSwapper/models/MicrosoftAspNetCoreMvcProblemDetails.ts deleted file mode 100644 index 04af0af71e5..00000000000 --- a/packages/swapper/src/swappers/ChainflipSwapper/models/MicrosoftAspNetCoreMvcProblemDetails.ts +++ /dev/null @@ -1,101 +0,0 @@ -// @ts-nocheck -/* tslint:disable */ -/* eslint-disable */ -/** - * Chainflip Broker as a Service - * Run your own Chainflip Broker without any hassle. - * - * The version of the OpenAPI document: v1 - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - -import { exists, mapValues } from '../runtime'; -/** - * - * @export - * @interface MicrosoftAspNetCoreMvcProblemDetails - */ -export interface MicrosoftAspNetCoreMvcProblemDetails { - [key: string]: any | any; - /** - * A URI reference [RFC3986] that identifies the problem type. This specification encourages that, when dereferenced, it provide human-readable documentation for the problem type (e.g., using HTML [W3C.REC-html5-20141028]). When this member is not present, its value is assumed to be "about:blank". - * @type {string} - * @memberof MicrosoftAspNetCoreMvcProblemDetails - */ - type?: string | null; - /** - * A short, human-readable summary of the problem type. It SHOULD NOT change from occurrence to occurrence of the problem, except for purposes of localization(e.g., using proactive content negotiation; see[RFC7231], Section 3.4). - * @type {string} - * @memberof MicrosoftAspNetCoreMvcProblemDetails - */ - title?: string | null; - /** - * The HTTP status code([RFC7231], Section 6) generated by the origin server for this occurrence of the problem. - * @type {number} - * @memberof MicrosoftAspNetCoreMvcProblemDetails - */ - status?: number | null; - /** - * A human-readable explanation specific to this occurrence of the problem. - * @type {string} - * @memberof MicrosoftAspNetCoreMvcProblemDetails - */ - detail?: string | null; - /** - * A URI reference that identifies the specific occurrence of the problem. It may or may not yield further information if dereferenced. - * @type {string} - * @memberof MicrosoftAspNetCoreMvcProblemDetails - */ - instance?: string | null; -} - -/** - * Check if a given object implements the MicrosoftAspNetCoreMvcProblemDetails interface. - */ -export function instanceOfMicrosoftAspNetCoreMvcProblemDetails(value: object): boolean { - let isInstance = true; - - return isInstance; -} - -export function MicrosoftAspNetCoreMvcProblemDetailsFromJSON(json: any): MicrosoftAspNetCoreMvcProblemDetails { - return MicrosoftAspNetCoreMvcProblemDetailsFromJSONTyped(json, false); -} - -export function MicrosoftAspNetCoreMvcProblemDetailsFromJSONTyped(json: any, ignoreDiscriminator: boolean): MicrosoftAspNetCoreMvcProblemDetails { - if ((json === undefined) || (json === null)) { - return json; - } - return { - - ...json, - 'type': !exists(json, 'type') ? undefined : json['type'], - 'title': !exists(json, 'title') ? undefined : json['title'], - 'status': !exists(json, 'status') ? undefined : json['status'], - 'detail': !exists(json, 'detail') ? undefined : json['detail'], - 'instance': !exists(json, 'instance') ? undefined : json['instance'], - }; -} - -export function MicrosoftAspNetCoreMvcProblemDetailsToJSON(value?: MicrosoftAspNetCoreMvcProblemDetails | null): any { - if (value === undefined) { - return undefined; - } - if (value === null) { - return null; - } - return { - - ...value, - 'type': value.type, - 'title': value.title, - 'status': value.status, - 'detail': value.detail, - 'instance': value.instance, - }; -} - diff --git a/packages/swapper/src/swappers/ChainflipSwapper/models/MicrosoftAspNetCoreMvcValidationProblemDetails.ts b/packages/swapper/src/swappers/ChainflipSwapper/models/MicrosoftAspNetCoreMvcValidationProblemDetails.ts deleted file mode 100644 index 60c433ef5e9..00000000000 --- a/packages/swapper/src/swappers/ChainflipSwapper/models/MicrosoftAspNetCoreMvcValidationProblemDetails.ts +++ /dev/null @@ -1,109 +0,0 @@ -// @ts-nocheck -/* tslint:disable */ -/* eslint-disable */ -/** - * Chainflip Broker as a Service - * Run your own Chainflip Broker without any hassle. - * - * The version of the OpenAPI document: v1 - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - -import { exists, mapValues } from '../runtime'; -/** - * - * @export - * @interface MicrosoftAspNetCoreMvcValidationProblemDetails - */ -export interface MicrosoftAspNetCoreMvcValidationProblemDetails { - [key: string]: any | any; - /** - * A URI reference [RFC3986] that identifies the problem type. This specification encourages that, when dereferenced, it provide human-readable documentation for the problem type (e.g., using HTML [W3C.REC-html5-20141028]). When this member is not present, its value is assumed to be "about:blank". - * @type {string} - * @memberof MicrosoftAspNetCoreMvcValidationProblemDetails - */ - type?: string | null; - /** - * A short, human-readable summary of the problem type. It SHOULD NOT change from occurrence to occurrence of the problem, except for purposes of localization(e.g., using proactive content negotiation; see[RFC7231], Section 3.4). - * @type {string} - * @memberof MicrosoftAspNetCoreMvcValidationProblemDetails - */ - title?: string | null; - /** - * The HTTP status code([RFC7231], Section 6) generated by the origin server for this occurrence of the problem. - * @type {number} - * @memberof MicrosoftAspNetCoreMvcValidationProblemDetails - */ - status?: number | null; - /** - * A human-readable explanation specific to this occurrence of the problem. - * @type {string} - * @memberof MicrosoftAspNetCoreMvcValidationProblemDetails - */ - detail?: string | null; - /** - * A URI reference that identifies the specific occurrence of the problem. It may or may not yield further information if dereferenced. - * @type {string} - * @memberof MicrosoftAspNetCoreMvcValidationProblemDetails - */ - instance?: string | null; - /** - * The validation errors associated with this problem details. - * @type {{ [key: string]: Array; }} - * @memberof MicrosoftAspNetCoreMvcValidationProblemDetails - */ - errors?: { [key: string]: Array; }; -} - -/** - * Check if a given object implements the MicrosoftAspNetCoreMvcValidationProblemDetails interface. - */ -export function instanceOfMicrosoftAspNetCoreMvcValidationProblemDetails(value: object): boolean { - let isInstance = true; - - return isInstance; -} - -export function MicrosoftAspNetCoreMvcValidationProblemDetailsFromJSON(json: any): MicrosoftAspNetCoreMvcValidationProblemDetails { - return MicrosoftAspNetCoreMvcValidationProblemDetailsFromJSONTyped(json, false); -} - -export function MicrosoftAspNetCoreMvcValidationProblemDetailsFromJSONTyped(json: any, ignoreDiscriminator: boolean): MicrosoftAspNetCoreMvcValidationProblemDetails { - if ((json === undefined) || (json === null)) { - return json; - } - return { - - ...json, - 'type': !exists(json, 'type') ? undefined : json['type'], - 'title': !exists(json, 'title') ? undefined : json['title'], - 'status': !exists(json, 'status') ? undefined : json['status'], - 'detail': !exists(json, 'detail') ? undefined : json['detail'], - 'instance': !exists(json, 'instance') ? undefined : json['instance'], - 'errors': !exists(json, 'errors') ? undefined : json['errors'], - }; -} - -export function MicrosoftAspNetCoreMvcValidationProblemDetailsToJSON(value?: MicrosoftAspNetCoreMvcValidationProblemDetails | null): any { - if (value === undefined) { - return undefined; - } - if (value === null) { - return null; - } - return { - - ...value, - 'type': value.type, - 'title': value.title, - 'status': value.status, - 'detail': value.detail, - 'instance': value.instance, - 'errors': value.errors, - }; -} - diff --git a/packages/swapper/src/swappers/ChainflipSwapper/models/index.ts b/packages/swapper/src/swappers/ChainflipSwapper/models/index.ts index dc72788d43a..17079e01819 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/models/index.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/models/index.ts @@ -1,18 +1,10 @@ -// @ts-nocheck /* tslint:disable */ /* eslint-disable */ -export * from './ChainflipBaasAssetsAssetInfo'; -export * from './ChainflipBaasAssetsAssetsResponse'; -export * from './ChainflipBaasBalanceBalanceResponse'; -export * from './ChainflipBaasFeesFeesResponse'; -export * from './ChainflipBaasNetworksNetworkInfo'; -export * from './ChainflipBaasNetworksNetworksResponse'; export * from './ChainflipBaasQuoteBoostQuote'; export * from './ChainflipBaasQuotePoolFee'; export * from './ChainflipBaasQuotePoolInfo'; export * from './ChainflipBaasQuoteQuote'; export * from './ChainflipBaasQuoteQuoteFee'; -export * from './ChainflipBaasRpcRpcRequest'; export * from './ChainflipBaasStatusAffiliateBroker'; export * from './ChainflipBaasStatusBoost'; export * from './ChainflipBaasStatusCcmParameters'; @@ -29,8 +21,4 @@ export * from './ChainflipBaasStatusReason'; export * from './ChainflipBaasStatusStatusResponse'; export * from './ChainflipBaasStatusSwap'; export * from './ChainflipBaasStatusSwapStatus'; -export * from './ChainflipBaasSwapAdvancedSwapRequest'; -export * from './ChainflipBaasSwapCcmRequest'; export * from './ChainflipBaasSwapDepositAddress'; -export * from './MicrosoftAspNetCoreMvcProblemDetails'; -export * from './MicrosoftAspNetCoreMvcValidationProblemDetails'; From ef79b52c88149d1fb3743bd327093334788d4499 Mon Sep 17 00:00:00 2001 From: David Cumps Date: Thu, 24 Oct 2024 01:05:38 +0200 Subject: [PATCH 029/127] chore: remove polkadot todo --- packages/swapper/src/swappers/ChainflipSwapper/constants.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/swapper/src/swappers/ChainflipSwapper/constants.ts b/packages/swapper/src/swappers/ChainflipSwapper/constants.ts index 07be8358fdf..a4afdcc91db 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/constants.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/constants.ts @@ -7,7 +7,6 @@ export const ChainflipSupportedChainIds = [ KnownChainIds.ArbitrumMainnet, KnownChainIds.BitcoinMainnet, KnownChainIds.SolanaMainnet, - // TODO: Add Polkadot ] as const export type ChainflipSupportedChainId = (typeof ChainflipSupportedChainIds)[number] @@ -17,7 +16,6 @@ export const ChainflipSupportedAssets = { [KnownChainIds.ArbitrumMainnet]: ['eth', 'usdc'], [KnownChainIds.BitcoinMainnet]: ['btc'], [KnownChainIds.SolanaMainnet]: ['sol', 'usdc'], - // TODO: Add Polkadot } export const chainIdToChainflipNetwork: Partial> = { @@ -25,7 +23,6 @@ export const chainIdToChainflipNetwork: Partial> = [KnownChainIds.ArbitrumMainnet]: 'arb', [KnownChainIds.BitcoinMainnet]: 'btc', [KnownChainIds.SolanaMainnet]: 'sol', - // TODO: Add Polkadot } export const assetGasLimits: Partial> = { From fea992cb0febcb19081919af1a4c5ed4c96fca6e Mon Sep 17 00:00:00 2001 From: David Cumps Date: Thu, 24 Oct 2024 01:31:54 +0200 Subject: [PATCH 030/127] refactor: clarify networkfee crypto base unit naming --- .../getChainflipTradeQuote/getTradeQuote.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts b/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts index b8d6ab1eb38..6fc7ff4edec 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts @@ -122,7 +122,7 @@ export const getChainflipTradeQuote = async ( const defaultSlippage = getDefaultSlippageDecimalPercentageForSwapper(SwapperName.Chainflip); - const getGasFee = async () => { + const getNetworkFeeCryptoBaseUnit = async () => { const { chainNamespace } = fromAssetId(sellAsset.assetId); switch (chainNamespace) { @@ -231,7 +231,7 @@ export const getChainflipTradeQuote = async ( buyAmountAfterFeesCryptoBaseUnit: singleQuoteResponse.boostQuote.egressAmountNative!, sellAmountIncludingProtocolFeesCryptoBaseUnit: singleQuoteResponse.boostQuote.ingressAmountNative!, feeData: { - networkFeeCryptoBaseUnit: await getGasFee(), + networkFeeCryptoBaseUnit: await getNetworkFeeCryptoBaseUnit(), protocolFees: getProtocolFees(singleQuoteResponse.boostQuote), }, rate: boostRate, @@ -273,7 +273,7 @@ export const getChainflipTradeQuote = async ( buyAmountAfterFeesCryptoBaseUnit: singleQuoteResponse.egressAmountNative!, sellAmountIncludingProtocolFeesCryptoBaseUnit: singleQuoteResponse.ingressAmountNative!, feeData: { - networkFeeCryptoBaseUnit: await getGasFee(), + networkFeeCryptoBaseUnit: await getNetworkFeeCryptoBaseUnit(), protocolFees: getProtocolFees(singleQuoteResponse), }, rate: rate, From ee0d7bd47ab3642a01501e1e983534e7dd679f6e Mon Sep 17 00:00:00 2001 From: David Cumps Date: Thu, 24 Oct 2024 01:34:39 +0200 Subject: [PATCH 031/127] refactor: turn asset symbols into asset ids --- .../ChainflipSwapper/ChainflipSwapper.ts | 6 +-- .../swappers/ChainflipSwapper/constants.ts | 23 +++++++--- .../getChainflipTradeQuote/getTradeQuote.ts | 43 ++++++++----------- .../txFeeHelpers/utxoTxFees/getUtxoTxFees.ts | 11 ++--- .../ChainflipSwapper/utils/helpers.ts | 8 ++-- 5 files changed, 46 insertions(+), 45 deletions(-) diff --git a/packages/swapper/src/swappers/ChainflipSwapper/ChainflipSwapper.ts b/packages/swapper/src/swappers/ChainflipSwapper/ChainflipSwapper.ts index 9455babe838..165ffd9ce8b 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/ChainflipSwapper.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/ChainflipSwapper.ts @@ -3,14 +3,14 @@ import type { Asset } from '@shapeshiftoss/types' import type { BuyAssetBySellIdInput, Swapper } from '../../types' import { CHAINFLIP_SUPPORTED_CHAIN_IDS } from './constants' -import { isSupportedAsset } from "./utils/helpers"; +import { isSupportedAssetId } from "./utils/helpers"; export const chainflipSwapper: Swapper = { filterAssetIdsBySellable: (assets: Asset[]): Promise => { return Promise.resolve( assets .filter(asset => CHAINFLIP_SUPPORTED_CHAIN_IDS.sell.includes(asset.chainId)) - .filter(asset => isSupportedAsset(asset.chainId, asset.symbol)) + .filter(asset => isSupportedAssetId(asset.chainId, asset.assetId)) .map(asset => asset.assetId), ) }, @@ -19,7 +19,7 @@ export const chainflipSwapper: Swapper = { return Promise.resolve( input.assets .filter(asset => CHAINFLIP_SUPPORTED_CHAIN_IDS.buy.includes(asset.chainId)) - .filter(asset => isSupportedAsset(asset.chainId, asset.symbol)) + .filter(asset => isSupportedAssetId(asset.chainId, asset.assetId)) .map(asset => asset.assetId), ) }, diff --git a/packages/swapper/src/swappers/ChainflipSwapper/constants.ts b/packages/swapper/src/swappers/ChainflipSwapper/constants.ts index a4afdcc91db..380f1bef116 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/constants.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/constants.ts @@ -1,7 +1,18 @@ -import type { ChainId } from '@shapeshiftoss/caip' +import type { ChainId, AssetId } from '@shapeshiftoss/caip' import { Asset, KnownChainIds } from "@shapeshiftoss/types"; import { SupportedChainIds, SwapperName, SwapSource } from '../../types' +// TODO: Get correct caip-19s +const ETHEREUM_ETH_ASSET_ID: AssetId = 'eip155:1/erc20:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' +const ETHEREUM_FLIP_ASSET_ID: AssetId = 'eip155:1/erc20:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' +const ETHEREUM_USDC_ASSET_ID: AssetId = 'eip155:1/erc20:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' +const ETHEREUM_USDT_ASSET_ID: AssetId = 'eip155:1/erc20:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' +const ARBITRUM_ETH_ASSET_ID: AssetId = 'eip155:1/erc20:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' +const ARBITRUM_USDC_ASSET_ID: AssetId = 'eip155:1/erc20:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' +const BITCOIN_BTC_ASSET_ID: AssetId = 'eip155:1/erc20:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' +const SOLANA_SOL_ASSET_ID: AssetId = 'eip155:1/erc20:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' +const SOLANA_USDC_ASSET_ID: AssetId = 'eip155:1/erc20:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' + export const ChainflipSupportedChainIds = [ KnownChainIds.EthereumMainnet, KnownChainIds.ArbitrumMainnet, @@ -11,11 +22,11 @@ export const ChainflipSupportedChainIds = [ export type ChainflipSupportedChainId = (typeof ChainflipSupportedChainIds)[number] -export const ChainflipSupportedAssets = { - [KnownChainIds.EthereumMainnet]: ['eth', 'flip', 'usdc', 'usdt'], - [KnownChainIds.ArbitrumMainnet]: ['eth', 'usdc'], - [KnownChainIds.BitcoinMainnet]: ['btc'], - [KnownChainIds.SolanaMainnet]: ['sol', 'usdc'], +export const ChainflipSupportedAssetIdsByChainId: Partial> = { + [KnownChainIds.EthereumMainnet]: [ETHEREUM_ETH_ASSET_ID, ETHEREUM_FLIP_ASSET_ID, ETHEREUM_USDC_ASSET_ID, ETHEREUM_USDT_ASSET_ID], + [KnownChainIds.ArbitrumMainnet]: [ARBITRUM_ETH_ASSET_ID, ARBITRUM_USDC_ASSET_ID], + [KnownChainIds.BitcoinMainnet]: [BITCOIN_BTC_ASSET_ID], + [KnownChainIds.SolanaMainnet]: [SOLANA_SOL_ASSET_ID, SOLANA_USDC_ASSET_ID], } export const chainIdToChainflipNetwork: Partial> = { diff --git a/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts b/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts index 6fc7ff4edec..2ff0b840864 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts @@ -1,7 +1,8 @@ -import {v4 as uuid} from "uuid"; -import {Err, Ok, Result} from "@sniptt/monads"; -import {KnownChainIds} from "@shapeshiftoss/types"; -import {AssetId, CHAIN_NAMESPACE, fromAssetId} from "@shapeshiftoss/caip"; +import { v4 as uuid } from "uuid"; +import { AxiosError } from "axios"; +import { Err, Ok, Result } from "@sniptt/monads"; +import { KnownChainIds } from "@shapeshiftoss/types"; +import { AssetId, CHAIN_NAMESPACE, fromAssetId } from "@shapeshiftoss/caip"; import { type GetEvmTradeQuoteInput, @@ -13,7 +14,8 @@ import { TradeQuote, TradeQuoteError } from "../../../types"; -import {getRate, makeSwapErrorRight} from "../../../utils"; +import { getRate, makeSwapErrorRight } from "../../../utils"; +import { getDefaultSlippageDecimalPercentageForSwapper } from "../../../constants"; import { CHAINFLIP_BOOST_SWAP_SOURCE, @@ -23,13 +25,11 @@ import { chainIdToChainflipNetwork, usdcAsset } from "../constants"; -import {isSupportedAsset, isSupportedChainId} from "../utils/helpers"; -import {chainflipService} from "../utils/chainflipService"; -import {ChainflipBaasQuoteQuote, ChainflipBaasQuoteQuoteFee} from "../models"; -import {getEvmTxFees} from "../txFeeHelpers/evmTxFees/getEvmTxFees"; -import {getDefaultSlippageDecimalPercentageForSwapper} from "../../../constants"; -import {AxiosError} from "axios"; -// import { getUtxoTxFees } from "../txFeeHelpers/utxoTxFees/getUtxoTxFees"; +import { ChainflipBaasQuoteQuote, ChainflipBaasQuoteQuoteFee } from "../models"; +import { isSupportedAssetId, isSupportedChainId } from "../utils/helpers"; +import { chainflipService } from "../utils/chainflipService"; +import { getEvmTxFees } from "../txFeeHelpers/evmTxFees/getEvmTxFees"; +import { getUtxoTxFees } from "../txFeeHelpers/utxoTxFees/getUtxoTxFees"; export const getChainflipTradeQuote = async ( input: GetTradeQuoteInput, @@ -62,7 +62,7 @@ export const getChainflipTradeQuote = async ( ) } - if (!isSupportedAsset(sellAsset.chainId, sellAsset.symbol)) { + if (!isSupportedAssetId(sellAsset.chainId, sellAsset.assetId)) { return Err( makeSwapErrorRight({ message: `asset '${sellAsset.name}' on chainId '${sellAsset.chainId}' not supported`, @@ -72,7 +72,7 @@ export const getChainflipTradeQuote = async ( ) } - if (!isSupportedAsset(buyAsset.chainId, buyAsset.symbol)) { + if (!isSupportedAssetId(buyAsset.chainId, buyAsset.assetId)) { return Err( makeSwapErrorRight({ message: `asset '${buyAsset.name}' on chainId '${buyAsset.chainId}' not supported`, @@ -136,16 +136,11 @@ export const getChainflipTradeQuote = async ( } case CHAIN_NAMESPACE.Utxo: { - // TODO: Figure out BTC gas calc - return undefined; - // const sellAdapter = deps.assertGetUtxoChainAdapter(sellAsset.chainId) - // return await getUtxoTxFees({ - // sellAmountCryptoBaseUnit: sellAmount, - // vault, - // opReturnData, - // pubkey, - // sellAdapter, - // }) + const sellAdapter = deps.assertGetUtxoChainAdapter(sellAsset.chainId) + return await getUtxoTxFees({ + sellAmountCryptoBaseUnit: sellAmount, + sellAdapter, + }) } case CHAIN_NAMESPACE.Solana: { diff --git a/packages/swapper/src/swappers/ChainflipSwapper/txFeeHelpers/utxoTxFees/getUtxoTxFees.ts b/packages/swapper/src/swappers/ChainflipSwapper/txFeeHelpers/utxoTxFees/getUtxoTxFees.ts index d63957087b4..48c28c527c2 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/txFeeHelpers/utxoTxFees/getUtxoTxFees.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/txFeeHelpers/utxoTxFees/getUtxoTxFees.ts @@ -3,24 +3,19 @@ import type { UtxoChainId } from '@shapeshiftoss/types' import { bn } from '@shapeshiftoss/utils' type GetUtxoTxFeesInput = { - opReturnData: string - vault: string sellAmountCryptoBaseUnit: string sellAdapter: UtxoChainAdapter - pubkey: string } export const getUtxoTxFees = async ({ - opReturnData, - vault, sellAmountCryptoBaseUnit, sellAdapter, - pubkey, }: GetUtxoTxFeesInput): Promise => { + // TODO: Get Chainflip BTC vault address const getFeeDataInput: GetFeeDataInput = { - to: vault, + to: 'vault', value: sellAmountCryptoBaseUnit, - chainSpecific: { pubkey, opReturnData }, + chainSpecific: { pubkey: '' }, } const feeDataOptions = await sellAdapter.getFeeData(getFeeDataInput) diff --git a/packages/swapper/src/swappers/ChainflipSwapper/utils/helpers.ts b/packages/swapper/src/swappers/ChainflipSwapper/utils/helpers.ts index 7828ae59923..1c75e6325bf 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/utils/helpers.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/utils/helpers.ts @@ -1,12 +1,12 @@ -import { type ChainId } from '@shapeshiftoss/caip' +import { type ChainId, type AssetId } from '@shapeshiftoss/caip' import type { ChainflipSupportedChainId } from '../constants' -import { ChainflipSupportedChainIds, ChainflipSupportedAssets } from "../constants"; +import { ChainflipSupportedChainIds, ChainflipSupportedAssetIdsByChainId } from "../constants"; export const isSupportedChainId = (chainId: ChainId): chainId is ChainflipSupportedChainId => { return ChainflipSupportedChainIds.includes(chainId as ChainflipSupportedChainId) } -export const isSupportedAsset = (chainId: ChainId, symbol: string): chainId is ChainflipSupportedChainId => { - return ChainflipSupportedAssets[chainId as ChainflipSupportedChainId].includes(symbol.toLowerCase()) +export const isSupportedAssetId = (chainId: ChainId, assetId: AssetId): chainId is ChainflipSupportedChainId => { + return ChainflipSupportedAssetIdsByChainId[chainId as ChainflipSupportedChainId]!.includes(assetId) } From 089fff0cae48fef8186691d7a532ee7bae030402 Mon Sep 17 00:00:00 2001 From: David Cumps Date: Thu, 24 Oct 2024 01:56:37 +0200 Subject: [PATCH 032/127] feat: use correct caip-19s --- .../swappers/ChainflipSwapper/constants.ts | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/packages/swapper/src/swappers/ChainflipSwapper/constants.ts b/packages/swapper/src/swappers/ChainflipSwapper/constants.ts index 380f1bef116..e7e23b29227 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/constants.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/constants.ts @@ -2,16 +2,18 @@ import type { ChainId, AssetId } from '@shapeshiftoss/caip' import { Asset, KnownChainIds } from "@shapeshiftoss/types"; import { SupportedChainIds, SwapperName, SwapSource } from '../../types' -// TODO: Get correct caip-19s -const ETHEREUM_ETH_ASSET_ID: AssetId = 'eip155:1/erc20:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' -const ETHEREUM_FLIP_ASSET_ID: AssetId = 'eip155:1/erc20:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' +const ETHEREUM_ETH_ASSET_ID: AssetId = 'eip155:1/slip44:60' +const ETHEREUM_FLIP_ASSET_ID: AssetId = 'eip155:1/erc20:0x826180541412d574cf1336d22c0c0a287822678a' const ETHEREUM_USDC_ASSET_ID: AssetId = 'eip155:1/erc20:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' -const ETHEREUM_USDT_ASSET_ID: AssetId = 'eip155:1/erc20:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' -const ARBITRUM_ETH_ASSET_ID: AssetId = 'eip155:1/erc20:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' -const ARBITRUM_USDC_ASSET_ID: AssetId = 'eip155:1/erc20:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' -const BITCOIN_BTC_ASSET_ID: AssetId = 'eip155:1/erc20:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' -const SOLANA_SOL_ASSET_ID: AssetId = 'eip155:1/erc20:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' -const SOLANA_USDC_ASSET_ID: AssetId = 'eip155:1/erc20:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' +const ETHEREUM_USDT_ASSET_ID: AssetId = 'eip155:1/erc20:0xdac17f958d2ee523a2206206994597c13d831ec7' + +const ARBITRUM_ETH_ASSET_ID: AssetId = 'eip155:42161/slip44:60' +const ARBITRUM_USDC_ASSET_ID: AssetId = 'eip155:42161/erc20:0xaf88d065e77c8cc2239327c5edb3a432268e5831' + +const BITCOIN_BTC_ASSET_ID: AssetId = 'bip122:000000000019d6689c085ae165831e93/slip44:0"' + +const SOLANA_SOL_ASSET_ID: AssetId = 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/slip44:501"' +const SOLANA_USDC_ASSET_ID: AssetId = 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/token:EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v' export const ChainflipSupportedChainIds = [ KnownChainIds.EthereumMainnet, From 1d25ce989e2bf99e950101806fcf50542889a307 Mon Sep 17 00:00:00 2001 From: David Cumps Date: Thu, 24 Oct 2024 02:00:50 +0200 Subject: [PATCH 033/127] feat: place dca swaps behind feature toggle --- .env.base | 1 + .../ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts | 5 +++++ packages/swapper/src/types.ts | 1 + src/config.ts | 1 + src/state/slices/preferencesSlice/preferencesSlice.ts | 2 ++ 5 files changed, 10 insertions(+) diff --git a/.env.base b/.env.base index 9962772bd99..6c99c7081e1 100644 --- a/.env.base +++ b/.env.base @@ -61,6 +61,7 @@ REACT_APP_FEATURE_READ_ONLY_ASSETS=true # swapper feature flags - other .env files will override these REACT_APP_FEATURE_CHAINFLIP=true +REACT_APP_FEATURE_CHAINFLIP_DCA=true REACT_APP_FEATURE_COWSWAP=true REACT_APP_FEATURE_LIFI_SWAP=true REACT_APP_FEATURE_THOR_SWAP=true diff --git a/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts b/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts index 2ff0b840864..581fb4878b7 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts @@ -199,6 +199,11 @@ export const getChainflipTradeQuote = async ( for (const singleQuoteResponse of quoteResponse) { const isStreaming = singleQuoteResponse.type === "dca"; + + if (isStreaming && !deps.config.REACT_APP_FEATURE_CHAINFLIP_DCA) { + // Streaming swaps are not enabled yet + continue; + } if (singleQuoteResponse.boostQuote) { const boostRate = getRate({ diff --git a/packages/swapper/src/types.ts b/packages/swapper/src/types.ts index f7d8950e050..2f6b8b6c208 100644 --- a/packages/swapper/src/types.ts +++ b/packages/swapper/src/types.ts @@ -47,6 +47,7 @@ export type SwapperConfig = { REACT_APP_PORTALS_BASE_URL: string REACT_APP_FEATURE_ZRX_PERMIT2: boolean REACT_APP_ZRX_BASE_URL: string, + REACT_APP_FEATURE_CHAINFLIP_DCA: boolean, REACT_APP_CHAINFLIP_API_KEY: string REACT_APP_CHAINFLIP_API_URL: string } diff --git a/src/config.ts b/src/config.ts index f9dea0a819a..215b89d1990 100644 --- a/src/config.ts +++ b/src/config.ts @@ -175,6 +175,7 @@ const validators = { REACT_APP_FEATURE_LIMIT_ORDERS: bool({ default: false }), REACT_APP_ZRX_BASE_URL: url(), REACT_APP_FEATURE_CHAINFLIP: bool({ default: false }), + REACT_APP_FEATURE_CHAINFLIP_DCA: bool({ default: false }), REACT_APP_CHAINFLIP_API_KEY: str(), REACT_APP_CHAINFLIP_API_URL: url(), REACT_APP_FEATURE_PUBLIC_TRADE_ROUTE: bool({ default: false }), diff --git a/src/state/slices/preferencesSlice/preferencesSlice.ts b/src/state/slices/preferencesSlice/preferencesSlice.ts index 855f4b07aa6..76d2f22b7c1 100644 --- a/src/state/slices/preferencesSlice/preferencesSlice.ts +++ b/src/state/slices/preferencesSlice/preferencesSlice.ts @@ -67,6 +67,7 @@ export type FeatureFlags = { FoxPageGovernance: boolean LimitOrders: boolean, Chainflip: boolean, + ChainflipDca: boolean, PublicTradeRoute: boolean } @@ -160,6 +161,7 @@ const initialState: Preferences = { FoxPageGovernance: getConfig().REACT_APP_FEATURE_FOX_PAGE_GOVERNANCE, LimitOrders: getConfig().REACT_APP_FEATURE_LIMIT_ORDERS, Chainflip: getConfig().REACT_APP_FEATURE_CHAINFLIP, + ChainflipDca: getConfig().REACT_APP_FEATURE_CHAINFLIP_DCA, PublicTradeRoute: getConfig().REACT_APP_FEATURE_PUBLIC_TRADE_ROUTE, }, selectedLocale: simpleLocale(), From a1661cdf7a6823fd502275034d1cf48a0e97bba7 Mon Sep 17 00:00:00 2001 From: David Cumps Date: Sat, 26 Oct 2024 00:31:23 +0200 Subject: [PATCH 034/127] chore: pull magic values into constants --- .../getChainflipTradeQuote/getTradeQuote.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts b/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts index 581fb4878b7..673acec6a43 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts @@ -31,6 +31,10 @@ import { chainflipService } from "../utils/chainflipService"; import { getEvmTxFees } from "../txFeeHelpers/evmTxFees/getEvmTxFees"; import { getUtxoTxFees } from "../txFeeHelpers/utxoTxFees/getUtxoTxFees"; +const CHAINFLIP_REGULAR_QUOTE = "regular"; +const CHAINFLIP_DCA_QUOTE = "dca"; +const CHAINFLIP_BAAS_COMMISSION = 5; + export const getChainflipTradeQuote = async ( input: GetTradeQuoteInput, deps: SwapperDeps, @@ -89,7 +93,7 @@ export const getChainflipTradeQuote = async ( const apiKey = deps.config.REACT_APP_CHAINFLIP_API_KEY; // Subtract the 0.05% BaaS fee to end up at the final displayed commissionBps - let serviceCommission = parseInt(commissionBps) - 5; + let serviceCommission = parseInt(commissionBps) - CHAINFLIP_BAAS_COMMISSION; if (serviceCommission < 0) serviceCommission = 0; @@ -198,7 +202,7 @@ export const getChainflipTradeQuote = async ( const quotes = []; for (const singleQuoteResponse of quoteResponse) { - const isStreaming = singleQuoteResponse.type === "dca"; + const isStreaming = singleQuoteResponse.type === CHAINFLIP_DCA_QUOTE; if (isStreaming && !deps.config.REACT_APP_FEATURE_CHAINFLIP_DCA) { // Streaming swaps are not enabled yet @@ -213,7 +217,7 @@ export const getChainflipTradeQuote = async ( buyAsset, }) - const boostSwapSource = singleQuoteResponse.type === "regular" + const boostSwapSource = singleQuoteResponse.type === CHAINFLIP_REGULAR_QUOTE ? CHAINFLIP_BOOST_SWAP_SOURCE : CHAINFLIP_DCA_BOOST_SWAP_SOURCE; @@ -255,7 +259,7 @@ export const getChainflipTradeQuote = async ( buyAsset, }) - const swapSource = singleQuoteResponse.type === "regular" + const swapSource = singleQuoteResponse.type === CHAINFLIP_REGULAR_QUOTE ? CHAINFLIP_SWAP_SOURCE : CHAINFLIP_DCA_SWAP_SOURCE; From 72f1c7e0c70320b68cb67cd051fe59b32e50c30f Mon Sep 17 00:00:00 2001 From: David Cumps Date: Sat, 26 Oct 2024 00:38:14 +0200 Subject: [PATCH 035/127] fix: pass pubkey for utxo estimation --- .../getChainflipTradeQuote/getTradeQuote.ts | 5 ++++- .../txFeeHelpers/utxoTxFees/getUtxoTxFees.ts | 6 ++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts b/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts index 673acec6a43..d980b2c7a68 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts @@ -6,7 +6,8 @@ import { AssetId, CHAIN_NAMESPACE, fromAssetId } from "@shapeshiftoss/caip"; import { type GetEvmTradeQuoteInput, - GetTradeQuoteInput, + GetTradeQuoteInput, + GetUtxoTradeQuoteInput, type ProtocolFee, SwapErrorRight, SwapperDeps, @@ -141,9 +142,11 @@ export const getChainflipTradeQuote = async ( case CHAIN_NAMESPACE.Utxo: { const sellAdapter = deps.assertGetUtxoChainAdapter(sellAsset.chainId) + const publicKey = (input as GetUtxoTradeQuoteInput).xpub!; return await getUtxoTxFees({ sellAmountCryptoBaseUnit: sellAmount, sellAdapter, + publicKey, }) } diff --git a/packages/swapper/src/swappers/ChainflipSwapper/txFeeHelpers/utxoTxFees/getUtxoTxFees.ts b/packages/swapper/src/swappers/ChainflipSwapper/txFeeHelpers/utxoTxFees/getUtxoTxFees.ts index 48c28c527c2..8f039036a43 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/txFeeHelpers/utxoTxFees/getUtxoTxFees.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/txFeeHelpers/utxoTxFees/getUtxoTxFees.ts @@ -4,18 +4,20 @@ import { bn } from '@shapeshiftoss/utils' type GetUtxoTxFeesInput = { sellAmountCryptoBaseUnit: string - sellAdapter: UtxoChainAdapter + sellAdapter: UtxoChainAdapter, + publicKey: string } export const getUtxoTxFees = async ({ sellAmountCryptoBaseUnit, sellAdapter, + publicKey }: GetUtxoTxFeesInput): Promise => { // TODO: Get Chainflip BTC vault address const getFeeDataInput: GetFeeDataInput = { to: 'vault', value: sellAmountCryptoBaseUnit, - chainSpecific: { pubkey: '' }, + chainSpecific: { pubkey: publicKey }, } const feeDataOptions = await sellAdapter.getFeeData(getFeeDataInput) From 3fd7b62ab926bda3fe3fc49a24ab18f04fe253cc Mon Sep 17 00:00:00 2001 From: David Cumps Date: Sat, 26 Oct 2024 00:59:10 +0200 Subject: [PATCH 036/127] fix: pass accountNumber --- .../ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts b/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts index d980b2c7a68..d97e7065ad4 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts @@ -43,6 +43,7 @@ export const getChainflipTradeQuote = async ( const { sellAsset, buyAsset, + accountNumber, sellAmountIncludingProtocolFeesCryptoBaseUnit: sellAmount, affiliateBps: commissionBps, } = input @@ -245,7 +246,7 @@ export const getChainflipTradeQuote = async ( source: boostSwapSource, buyAsset: buyAsset, sellAsset: sellAsset, - accountNumber: 0, + accountNumber: accountNumber ?? 0, // TODO: What to pass if accountNumber is undefined? allowanceContract: "0x0", // Chainflip does not use contracts estimatedExecutionTimeMs: singleQuoteResponse.boostQuote.estimatedDurationSeconds! * 1000 } @@ -287,7 +288,7 @@ export const getChainflipTradeQuote = async ( source: swapSource, buyAsset: buyAsset, sellAsset: sellAsset, - accountNumber: 0, + accountNumber: accountNumber ?? 0, // TODO: What to pass if accountNumber is undefined? allowanceContract: "0x0", // Chainflip does not use contracts estimatedExecutionTimeMs: singleQuoteResponse.estimatedDurationSeconds! * 1000 } From 519546bbaec6853e084db97dcb26187c7559b654 Mon Sep 17 00:00:00 2001 From: David Cumps Date: Sat, 26 Oct 2024 01:08:11 +0200 Subject: [PATCH 037/127] refactor: cleanup swapsource and rate code --- .../getChainflipTradeQuote/getTradeQuote.ts | 49 ++++++++++--------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts b/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts index d97e7065ad4..496d9947a50 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts @@ -94,7 +94,7 @@ export const getChainflipTradeQuote = async ( const brokerUrl = deps.config.REACT_APP_CHAINFLIP_API_URL const apiKey = deps.config.REACT_APP_CHAINFLIP_API_KEY; - // Subtract the 0.05% BaaS fee to end up at the final displayed commissionBps + // Subtract the BaaS fee to end up at the final displayed commissionBps let serviceCommission = parseInt(commissionBps) - CHAINFLIP_BAAS_COMMISSION; if (serviceCommission < 0) serviceCommission = 0; @@ -203,6 +203,21 @@ export const getChainflipTradeQuote = async ( return protocolFees; } + const getQuoteRate = (sellAmountCryptoBaseUnit: string, buyAmountCryptoBaseUnit: string) => { + return getRate({ + sellAmountCryptoBaseUnit: sellAmountCryptoBaseUnit, + buyAmountCryptoBaseUnit: buyAmountCryptoBaseUnit, + sellAsset, + buyAsset, + }); + } + + const getSwapSource = (swapType: string | undefined, isBoosted: boolean) => { + return swapType === CHAINFLIP_REGULAR_QUOTE + ? isBoosted ? CHAINFLIP_BOOST_SWAP_SOURCE : CHAINFLIP_SWAP_SOURCE + : isBoosted ? CHAINFLIP_DCA_BOOST_SWAP_SOURCE : CHAINFLIP_DCA_SWAP_SOURCE; + } + const quotes = []; for (const singleQuoteResponse of quoteResponse) { @@ -214,16 +229,9 @@ export const getChainflipTradeQuote = async ( } if (singleQuoteResponse.boostQuote) { - const boostRate = getRate({ - sellAmountCryptoBaseUnit: singleQuoteResponse.boostQuote.ingressAmountNative!, - buyAmountCryptoBaseUnit: singleQuoteResponse.boostQuote.egressAmountNative!, - sellAsset, - buyAsset, - }) - - const boostSwapSource = singleQuoteResponse.type === CHAINFLIP_REGULAR_QUOTE - ? CHAINFLIP_BOOST_SWAP_SOURCE - : CHAINFLIP_DCA_BOOST_SWAP_SOURCE; + const boostRate = getQuoteRate( + singleQuoteResponse.boostQuote.ingressAmountNative!, + singleQuoteResponse.boostQuote.egressAmountNative!); const boostTradeQuote: TradeQuote = { id: uuid(), @@ -243,7 +251,7 @@ export const getChainflipTradeQuote = async ( protocolFees: getProtocolFees(singleQuoteResponse.boostQuote), }, rate: boostRate, - source: boostSwapSource, + source: getSwapSource(singleQuoteResponse.type, true), buyAsset: buyAsset, sellAsset: sellAsset, accountNumber: accountNumber ?? 0, // TODO: What to pass if accountNumber is undefined? @@ -255,18 +263,11 @@ export const getChainflipTradeQuote = async ( quotes.push(boostTradeQuote); } - - const rate = getRate({ - sellAmountCryptoBaseUnit: singleQuoteResponse.ingressAmountNative!, - buyAmountCryptoBaseUnit: singleQuoteResponse.egressAmountNative!, - sellAsset, - buyAsset, - }) - const swapSource = singleQuoteResponse.type === CHAINFLIP_REGULAR_QUOTE - ? CHAINFLIP_SWAP_SOURCE - : CHAINFLIP_DCA_SWAP_SOURCE; - + const rate = getQuoteRate( + singleQuoteResponse.ingressAmountNative!, + singleQuoteResponse.egressAmountNative!); + const tradeQuote: TradeQuote = { id: uuid(), rate: rate, @@ -285,7 +286,7 @@ export const getChainflipTradeQuote = async ( protocolFees: getProtocolFees(singleQuoteResponse), }, rate: rate, - source: swapSource, + source: getSwapSource(singleQuoteResponse.type, false), buyAsset: buyAsset, sellAsset: sellAsset, accountNumber: accountNumber ?? 0, // TODO: What to pass if accountNumber is undefined? From 708a826ec63733d815642f6c4de44bc86bf8c30d Mon Sep 17 00:00:00 2001 From: David Cumps Date: Sat, 26 Oct 2024 01:45:44 +0200 Subject: [PATCH 038/127] fix: add feature flag to tests --- src/test/mocks/store.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/mocks/store.ts b/src/test/mocks/store.ts index 6fe451f78c7..ac0eaf1553a 100644 --- a/src/test/mocks/store.ts +++ b/src/test/mocks/store.ts @@ -123,6 +123,7 @@ export const mockStore: ReduxState = { FoxPageGovernance: false, LimitOrders: false, Chainflip: false, + ChainflipDca: false, PublicTradeRoute: false, }, selectedLocale: 'en', From 8a17ba64a2ef32c4e77a64fd3ddcea06fe661b39 Mon Sep 17 00:00:00 2001 From: David Cumps Date: Sat, 26 Oct 2024 02:03:27 +0200 Subject: [PATCH 039/127] fix: unwanted quote char snuck in --- packages/swapper/src/swappers/ChainflipSwapper/constants.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/swapper/src/swappers/ChainflipSwapper/constants.ts b/packages/swapper/src/swappers/ChainflipSwapper/constants.ts index e7e23b29227..5d428e08361 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/constants.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/constants.ts @@ -10,9 +10,9 @@ const ETHEREUM_USDT_ASSET_ID: AssetId = 'eip155:1/erc20:0xdac17f958d2ee523a22062 const ARBITRUM_ETH_ASSET_ID: AssetId = 'eip155:42161/slip44:60' const ARBITRUM_USDC_ASSET_ID: AssetId = 'eip155:42161/erc20:0xaf88d065e77c8cc2239327c5edb3a432268e5831' -const BITCOIN_BTC_ASSET_ID: AssetId = 'bip122:000000000019d6689c085ae165831e93/slip44:0"' +const BITCOIN_BTC_ASSET_ID: AssetId = 'bip122:000000000019d6689c085ae165831e93/slip44:0' -const SOLANA_SOL_ASSET_ID: AssetId = 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/slip44:501"' +const SOLANA_SOL_ASSET_ID: AssetId = 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/slip44:501' const SOLANA_USDC_ASSET_ID: AssetId = 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/token:EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v' export const ChainflipSupportedChainIds = [ From 12ae96731dbacf18b2991ec9415bec3d383edd8d Mon Sep 17 00:00:00 2001 From: David Cumps Date: Sat, 26 Oct 2024 02:15:32 +0200 Subject: [PATCH 040/127] style: be consistent in quotes style --- .../ChainflipSwapper/ChainflipSwapper.ts | 2 +- .../swappers/ChainflipSwapper/constants.ts | 32 +++++++------- .../swappers/ChainflipSwapper/endpoints.ts | 4 +- .../getChainflipTradeQuote/getTradeQuote.ts | 44 +++++++++---------- .../txFeeHelpers/evmTxFees/getEvmTxFees.ts | 4 +- .../ChainflipSwapper/utils/helpers.ts | 2 +- 6 files changed, 44 insertions(+), 44 deletions(-) diff --git a/packages/swapper/src/swappers/ChainflipSwapper/ChainflipSwapper.ts b/packages/swapper/src/swappers/ChainflipSwapper/ChainflipSwapper.ts index 165ffd9ce8b..f3db2a1cdf5 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/ChainflipSwapper.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/ChainflipSwapper.ts @@ -3,7 +3,7 @@ import type { Asset } from '@shapeshiftoss/types' import type { BuyAssetBySellIdInput, Swapper } from '../../types' import { CHAINFLIP_SUPPORTED_CHAIN_IDS } from './constants' -import { isSupportedAssetId } from "./utils/helpers"; +import { isSupportedAssetId } from './utils/helpers'; export const chainflipSwapper: Swapper = { filterAssetIdsBySellable: (assets: Asset[]): Promise => { diff --git a/packages/swapper/src/swappers/ChainflipSwapper/constants.ts b/packages/swapper/src/swappers/ChainflipSwapper/constants.ts index 5d428e08361..83dbe7d46e1 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/constants.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/constants.ts @@ -1,5 +1,5 @@ import type { ChainId, AssetId } from '@shapeshiftoss/caip' -import { Asset, KnownChainIds } from "@shapeshiftoss/types"; +import { Asset, KnownChainIds } from '@shapeshiftoss/types'; import { SupportedChainIds, SwapperName, SwapSource } from '../../types' const ETHEREUM_ETH_ASSET_ID: AssetId = 'eip155:1/slip44:60' @@ -39,12 +39,12 @@ export const chainIdToChainflipNetwork: Partial> = } export const assetGasLimits: Partial> = { - ["eth.eth"]: '34000', - ["flip.eth"]: '52000', - ["usdc.eth"]: '63000', - ["usdt.eth"]: '70000', - ["eth.arb"]: '100000', - ["usdc.arb"]: '100000', + ['eth.eth']: '34000', + ['flip.eth']: '52000', + ['usdc.eth']: '63000', + ['usdt.eth']: '70000', + ['eth.arb']: '100000', + ['usdc.arb']: '100000', } export const CHAINFLIP_SUPPORTED_CHAIN_IDS: SupportedChainIds = { @@ -58,15 +58,15 @@ export const CHAINFLIP_DCA_SWAP_SOURCE: SwapSource = `${SwapperName.Chainflip} export const CHAINFLIP_DCA_BOOST_SWAP_SOURCE: SwapSource = `${SwapperName.Chainflip} • DCA • Boost` export const usdcAsset: Asset = { - assetId: "eip155:1/erc20:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", + assetId: 'eip155:1/erc20:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', chainId: KnownChainIds.EthereumMainnet, - color: "#2373CB", - explorer:"https://etherscan.io", - explorerAddressLink:"https://etherscan.io/address/", - explorerTxLink:"https://etherscan.io/tx/", - icon:"https://rawcdn.githack.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png", - name:"USDC on Ethereum", + color: '#2373CB', + explorer:'https://etherscan.io', + explorerAddressLink:'https://etherscan.io/address/', + explorerTxLink:'https://etherscan.io/tx/', + icon:'https://rawcdn.githack.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + name:'USDC on Ethereum', precision: 6, - relatedAssetKey: "eip155:1/erc20:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", - symbol:"USDC" + relatedAssetKey: 'eip155:1/erc20:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', + symbol:'USDC' } diff --git a/packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts b/packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts index a7cb653f3c3..9570b3f5362 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts @@ -1,7 +1,7 @@ import type { Result } from '@sniptt/monads/build' -import { TxStatus } from "@shapeshiftoss/unchained-client"; -import type { InterpolationOptions } from "node-polyglot"; +import { TxStatus } from '@shapeshiftoss/unchained-client'; +import type { InterpolationOptions } from 'node-polyglot'; import type { GetTradeQuoteInput, diff --git a/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts b/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts index 496d9947a50..da04d04d230 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts @@ -1,8 +1,8 @@ -import { v4 as uuid } from "uuid"; -import { AxiosError } from "axios"; -import { Err, Ok, Result } from "@sniptt/monads"; -import { KnownChainIds } from "@shapeshiftoss/types"; -import { AssetId, CHAIN_NAMESPACE, fromAssetId } from "@shapeshiftoss/caip"; +import { v4 as uuid } from 'uuid'; +import { AxiosError } from 'axios'; +import { Err, Ok, Result } from '@sniptt/monads'; +import { KnownChainIds } from '@shapeshiftoss/types'; +import { AssetId, CHAIN_NAMESPACE, fromAssetId } from '@shapeshiftoss/caip'; import { type GetEvmTradeQuoteInput, @@ -14,9 +14,9 @@ import { SwapperName, TradeQuote, TradeQuoteError -} from "../../../types"; -import { getRate, makeSwapErrorRight } from "../../../utils"; -import { getDefaultSlippageDecimalPercentageForSwapper } from "../../../constants"; +} from '../../../types'; +import { getRate, makeSwapErrorRight } from '../../../utils'; +import { getDefaultSlippageDecimalPercentageForSwapper } from '../../../constants'; import { CHAINFLIP_BOOST_SWAP_SOURCE, @@ -25,15 +25,15 @@ import { CHAINFLIP_SWAP_SOURCE, chainIdToChainflipNetwork, usdcAsset -} from "../constants"; -import { ChainflipBaasQuoteQuote, ChainflipBaasQuoteQuoteFee } from "../models"; -import { isSupportedAssetId, isSupportedChainId } from "../utils/helpers"; -import { chainflipService } from "../utils/chainflipService"; -import { getEvmTxFees } from "../txFeeHelpers/evmTxFees/getEvmTxFees"; -import { getUtxoTxFees } from "../txFeeHelpers/utxoTxFees/getUtxoTxFees"; +} from '../constants'; +import { ChainflipBaasQuoteQuote, ChainflipBaasQuoteQuoteFee } from '../models'; +import { isSupportedAssetId, isSupportedChainId } from '../utils/helpers'; +import { chainflipService } from '../utils/chainflipService'; +import { getEvmTxFees } from '../txFeeHelpers/evmTxFees/getEvmTxFees'; +import { getUtxoTxFees } from '../txFeeHelpers/utxoTxFees/getUtxoTxFees'; -const CHAINFLIP_REGULAR_QUOTE = "regular"; -const CHAINFLIP_DCA_QUOTE = "dca"; +const CHAINFLIP_REGULAR_QUOTE = 'regular'; +const CHAINFLIP_DCA_QUOTE = 'dca'; const CHAINFLIP_BAAS_COMMISSION = 5; export const getChainflipTradeQuote = async ( @@ -107,7 +107,7 @@ export const getChainflipTradeQuote = async ( const error = maybeQuoteResponse.unwrapErr(); const cause = error.cause as AxiosError; - if (cause.message.includes("code 400") && cause.response!.data.detail.includes("Amount outside asset bounds")) { + if (cause.message.includes('code 400') && cause.response!.data.detail.includes('Amount outside asset bounds')) { return Err( makeSwapErrorRight({ message: cause.response!.data.detail, @@ -161,19 +161,19 @@ export const getChainflipTradeQuote = async ( } const getFeeAsset = (fee: ChainflipBaasQuoteQuoteFee) => { - if (fee.type === "ingress" || fee.type === "boost") + if (fee.type === 'ingress' || fee.type === 'boost') return sellAsset; - if (fee.type === "egress") + if (fee.type === 'egress') return buyAsset; - if (fee.type === "liquidity" && fee.asset == sellChainflipChainKey) + if (fee.type === 'liquidity' && fee.asset == sellChainflipChainKey) return sellAsset; - if (fee.type === "liquidity" && fee.asset == buyChainflipChainKey) + if (fee.type === 'liquidity' && fee.asset == buyChainflipChainKey) return buyAsset; - if (fee.type === "liquidity" && fee.asset == "usdc.eth") + if (fee.type === 'liquidity' && fee.asset == "usdc.eth") return usdcAsset; if (fee.type === "network") diff --git a/packages/swapper/src/swappers/ChainflipSwapper/txFeeHelpers/evmTxFees/getEvmTxFees.ts b/packages/swapper/src/swappers/ChainflipSwapper/txFeeHelpers/evmTxFees/getEvmTxFees.ts index 127bc4cf38f..c16138794da 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/txFeeHelpers/evmTxFees/getEvmTxFees.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/txFeeHelpers/evmTxFees/getEvmTxFees.ts @@ -1,6 +1,6 @@ import type { EvmChainAdapter } from '@shapeshiftoss/chain-adapters' import { evm } from '@shapeshiftoss/chain-adapters' -import { assetGasLimits } from "../../constants"; +import { assetGasLimits } from '../../constants'; type GetEvmTxFeesArgs = { adapter: EvmChainAdapter @@ -13,7 +13,7 @@ export const getEvmTxFees = async (args: GetEvmTxFeesArgs): Promise => { const { average } = await adapter.getGasFeeData() - const gasLimit = (args.sendAsset in assetGasLimits) ? assetGasLimits[args.sendAsset]! : "100000"; + const gasLimit = (args.sendAsset in assetGasLimits) ? assetGasLimits[args.sendAsset]! : '100000'; return evm.calcNetworkFeeCryptoBaseUnit({ ...average, diff --git a/packages/swapper/src/swappers/ChainflipSwapper/utils/helpers.ts b/packages/swapper/src/swappers/ChainflipSwapper/utils/helpers.ts index 1c75e6325bf..b23f7f542cb 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/utils/helpers.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/utils/helpers.ts @@ -1,7 +1,7 @@ import { type ChainId, type AssetId } from '@shapeshiftoss/caip' import type { ChainflipSupportedChainId } from '../constants' -import { ChainflipSupportedChainIds, ChainflipSupportedAssetIdsByChainId } from "../constants"; +import { ChainflipSupportedChainIds, ChainflipSupportedAssetIdsByChainId } from '../constants'; export const isSupportedChainId = (chainId: ChainId): chainId is ChainflipSupportedChainId => { return ChainflipSupportedChainIds.includes(chainId as ChainflipSupportedChainId) From c090d434e1732abc667a05a76b7dfd22c21b5931 Mon Sep 17 00:00:00 2001 From: David Cumps Date: Sat, 26 Oct 2024 02:23:53 +0200 Subject: [PATCH 041/127] chore: make prettier happy --- src/state/helpers.ts | 5 +++-- src/state/slices/preferencesSlice/preferencesSlice.ts | 6 +++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/state/helpers.ts b/src/state/helpers.ts index 6f0f6f3395c..2e5f6b01c4e 100644 --- a/src/state/helpers.ts +++ b/src/state/helpers.ts @@ -22,12 +22,13 @@ export const isCrossAccountTradeSupported = (swapperName: SwapperName) => { } export const getEnabledSwappers = ( - { ArbitrumBridge, Chainflip, Cowswap, LifiSwap, Portals, ThorSwap, ZrxSwap }: FeatureFlags, + { ArbitrumBridge, Chainflip, Cowswap, LifiSwap, Portals, ThorSwap, ZrxSwap }: FeatureFlags, isCrossAccountTrade: boolean, ): Record => { return { [SwapperName.ArbitrumBridge]: - ArbitrumBridge && (!isCrossAccountTrade || isCrossAccountTradeSupported(SwapperName.ArbitrumBridge)), + ArbitrumBridge && + (!isCrossAccountTrade || isCrossAccountTradeSupported(SwapperName.ArbitrumBridge)), [SwapperName.Chainflip]: Chainflip && (!isCrossAccountTrade || isCrossAccountTradeSupported(SwapperName.Chainflip)), [SwapperName.CowSwap]: diff --git a/src/state/slices/preferencesSlice/preferencesSlice.ts b/src/state/slices/preferencesSlice/preferencesSlice.ts index 76d2f22b7c1..a1f3686ebc5 100644 --- a/src/state/slices/preferencesSlice/preferencesSlice.ts +++ b/src/state/slices/preferencesSlice/preferencesSlice.ts @@ -65,9 +65,9 @@ export type FeatureFlags = { FoxPageFoxSection: boolean FoxPageFoxFarmingSection: boolean FoxPageGovernance: boolean - LimitOrders: boolean, - Chainflip: boolean, - ChainflipDca: boolean, + LimitOrders: boolean + Chainflip: boolean + ChainflipDca: boolean PublicTradeRoute: boolean } From 34ea201aa5ed075e45876b4a4d2bded3a34653ef Mon Sep 17 00:00:00 2001 From: David Cumps Date: Sat, 26 Oct 2024 03:19:01 +0200 Subject: [PATCH 042/127] fix: populate receiveAddress to get swap preview --- .../ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts b/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts index da04d04d230..1ef562ef7d9 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts @@ -44,6 +44,7 @@ export const getChainflipTradeQuote = async ( sellAsset, buyAsset, accountNumber, + receiveAddress, sellAmountIncludingProtocolFeesCryptoBaseUnit: sellAmount, affiliateBps: commissionBps, } = input @@ -236,7 +237,7 @@ export const getChainflipTradeQuote = async ( const boostTradeQuote: TradeQuote = { id: uuid(), rate: boostRate, - receiveAddress: "", + receiveAddress: receiveAddress, potentialAffiliateBps: commissionBps, affiliateBps: commissionBps, isStreaming: isStreaming, @@ -271,7 +272,7 @@ export const getChainflipTradeQuote = async ( const tradeQuote: TradeQuote = { id: uuid(), rate: rate, - receiveAddress: "", + receiveAddress: receiveAddress, potentialAffiliateBps: commissionBps, affiliateBps: commissionBps, isStreaming: isStreaming, From b253f4bfe1d155304d494da273f5d963d414cd6b Mon Sep 17 00:00:00 2001 From: David Cumps Date: Sat, 26 Oct 2024 11:37:39 +0200 Subject: [PATCH 043/127] refactor: make code consistent with styling and restructure folders --- .../ChainflipSwapper/ChainflipSwapper.ts | 6 +- .../ChainflipSwapper/ChainflipSwapperApi.ts | 11 ++ .../swappers/ChainflipSwapper/constants.ts | 11 +- .../swappers/ChainflipSwapper/endpoints.ts | 40 ------ .../swapperApi/checkTradeStatus.ts | 16 +++ .../getTradeQuote.ts | 114 +++++++++--------- .../swapperApi/getUnsignedEvmTransaction.ts | 65 ++++++++++ .../txFeeHelpers/evmTxFees/getEvmTxFees.ts | 5 +- .../txFeeHelpers/utxoTxFees/getUtxoTxFees.ts | 4 +- .../ChainflipSwapper/utils/helpers.ts | 2 +- 10 files changed, 167 insertions(+), 107 deletions(-) create mode 100644 packages/swapper/src/swappers/ChainflipSwapper/ChainflipSwapperApi.ts delete mode 100644 packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts create mode 100644 packages/swapper/src/swappers/ChainflipSwapper/swapperApi/checkTradeStatus.ts rename packages/swapper/src/swappers/ChainflipSwapper/{getChainflipTradeQuote => swapperApi}/getTradeQuote.ts (83%) create mode 100644 packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts diff --git a/packages/swapper/src/swappers/ChainflipSwapper/ChainflipSwapper.ts b/packages/swapper/src/swappers/ChainflipSwapper/ChainflipSwapper.ts index f3db2a1cdf5..48a4eff09a1 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/ChainflipSwapper.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/ChainflipSwapper.ts @@ -2,10 +2,14 @@ import type { AssetId } from '@shapeshiftoss/caip' import type { Asset } from '@shapeshiftoss/types' import type { BuyAssetBySellIdInput, Swapper } from '../../types' +import { executeEvmTransaction } from '../../utils' + import { CHAINFLIP_SUPPORTED_CHAIN_IDS } from './constants' -import { isSupportedAssetId } from './utils/helpers'; +import { isSupportedAssetId } from './utils/helpers' export const chainflipSwapper: Swapper = { + executeEvmTransaction, + filterAssetIdsBySellable: (assets: Asset[]): Promise => { return Promise.resolve( assets diff --git a/packages/swapper/src/swappers/ChainflipSwapper/ChainflipSwapperApi.ts b/packages/swapper/src/swappers/ChainflipSwapper/ChainflipSwapperApi.ts new file mode 100644 index 00000000000..eb2362a34f9 --- /dev/null +++ b/packages/swapper/src/swappers/ChainflipSwapper/ChainflipSwapperApi.ts @@ -0,0 +1,11 @@ +import type { SwapperApi } from '../../types' + +import { getTradeQuote } from './swapperApi/getTradeQuote' +import { getUnsignedEvmTransaction } from './swapperApi/getUnsignedEvmTransaction' +import { checkTradeStatus } from './swapperApi/checkTradeStatus' + +export const chainflipApi: SwapperApi = { + getTradeQuote, + getUnsignedEvmTransaction, + checkTradeStatus +} diff --git a/packages/swapper/src/swappers/ChainflipSwapper/constants.ts b/packages/swapper/src/swappers/ChainflipSwapper/constants.ts index 83dbe7d46e1..95a63bf2251 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/constants.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/constants.ts @@ -1,6 +1,11 @@ import type { ChainId, AssetId } from '@shapeshiftoss/caip' -import { Asset, KnownChainIds } from '@shapeshiftoss/types'; -import { SupportedChainIds, SwapperName, SwapSource } from '../../types' +import { Asset, KnownChainIds } from '@shapeshiftoss/types' + +import { + SupportedChainIds, + SwapperName, + SwapSource +} from '../../types' const ETHEREUM_ETH_ASSET_ID: AssetId = 'eip155:1/slip44:60' const ETHEREUM_FLIP_ASSET_ID: AssetId = 'eip155:1/erc20:0x826180541412d574cf1336d22c0c0a287822678a' @@ -52,7 +57,7 @@ export const CHAINFLIP_SUPPORTED_CHAIN_IDS: SupportedChainIds = { buy: ChainflipSupportedChainIds as unknown as ChainId[], } -export const CHAINFLIP_SWAP_SOURCE: SwapSource = SwapperName.Chainflip; +export const CHAINFLIP_SWAP_SOURCE: SwapSource = SwapperName.Chainflip export const CHAINFLIP_BOOST_SWAP_SOURCE: SwapSource = `${SwapperName.Chainflip} • Boost` export const CHAINFLIP_DCA_SWAP_SOURCE: SwapSource = `${SwapperName.Chainflip} • DCA` export const CHAINFLIP_DCA_BOOST_SWAP_SOURCE: SwapSource = `${SwapperName.Chainflip} • DCA • Boost` diff --git a/packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts b/packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts deleted file mode 100644 index 9570b3f5362..00000000000 --- a/packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts +++ /dev/null @@ -1,40 +0,0 @@ -import type { Result } from '@sniptt/monads/build' - -import { TxStatus } from '@shapeshiftoss/unchained-client'; -import type { InterpolationOptions } from 'node-polyglot'; - -import type { - GetTradeQuoteInput, - SwapErrorRight, - SwapperApi, - SwapperDeps, - TradeQuote, -} from '../../types' - -import { getChainflipTradeQuote } from './getChainflipTradeQuote/getTradeQuote' - -export const chainflipApi: SwapperApi = { - getTradeQuote: async ( - input: GetTradeQuoteInput, - deps: SwapperDeps, - ): Promise> => { - return await getChainflipTradeQuote( - input, - deps, - ) - }, - - // @ts-ignore - checkTradeStatus: async (input): Promise<{ - status: TxStatus - buyTxHash: string | undefined - message: string | [string, InterpolationOptions] | undefined - }> => { - // TODO: Implement - return { - buyTxHash: undefined, - status: TxStatus.Unknown, - message: undefined, - } - } -} diff --git a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/checkTradeStatus.ts b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/checkTradeStatus.ts new file mode 100644 index 00000000000..3da368379d3 --- /dev/null +++ b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/checkTradeStatus.ts @@ -0,0 +1,16 @@ +import type { InterpolationOptions } from 'node-polyglot' +import { TxStatus } from '@shapeshiftoss/unchained-client' + +// @ts-ignore +export const checkTradeStatus = async (input): Promise<{ + status: TxStatus + buyTxHash: string | undefined + message: string | [string, InterpolationOptions] | undefined +}> => { + // TODO: Implement + return { + buyTxHash: undefined, + status: TxStatus.Unknown, + message: undefined, + } +} \ No newline at end of file diff --git a/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts similarity index 83% rename from packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts rename to packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts index 1ef562ef7d9..002f2a0b867 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/getChainflipTradeQuote/getTradeQuote.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts @@ -1,8 +1,8 @@ -import { v4 as uuid } from 'uuid'; -import { AxiosError } from 'axios'; -import { Err, Ok, Result } from '@sniptt/monads'; -import { KnownChainIds } from '@shapeshiftoss/types'; -import { AssetId, CHAIN_NAMESPACE, fromAssetId } from '@shapeshiftoss/caip'; +import { v4 as uuid } from 'uuid' +import { AxiosError } from 'axios' +import { Err, Ok, Result } from '@sniptt/monads' +import { KnownChainIds } from '@shapeshiftoss/types' +import { AssetId, CHAIN_NAMESPACE, fromAssetId } from '@shapeshiftoss/caip' import { type GetEvmTradeQuoteInput, @@ -14,9 +14,9 @@ import { SwapperName, TradeQuote, TradeQuoteError -} from '../../../types'; -import { getRate, makeSwapErrorRight } from '../../../utils'; -import { getDefaultSlippageDecimalPercentageForSwapper } from '../../../constants'; +} from '../../../types' +import { getRate, makeSwapErrorRight } from '../../../utils' +import { getDefaultSlippageDecimalPercentageForSwapper } from '../../../constants' import { CHAINFLIP_BOOST_SWAP_SOURCE, @@ -25,18 +25,18 @@ import { CHAINFLIP_SWAP_SOURCE, chainIdToChainflipNetwork, usdcAsset -} from '../constants'; -import { ChainflipBaasQuoteQuote, ChainflipBaasQuoteQuoteFee } from '../models'; -import { isSupportedAssetId, isSupportedChainId } from '../utils/helpers'; -import { chainflipService } from '../utils/chainflipService'; -import { getEvmTxFees } from '../txFeeHelpers/evmTxFees/getEvmTxFees'; -import { getUtxoTxFees } from '../txFeeHelpers/utxoTxFees/getUtxoTxFees'; +} from '../constants' +import { ChainflipBaasQuoteQuote, ChainflipBaasQuoteQuoteFee } from '../models' +import { isSupportedAssetId, isSupportedChainId } from '../utils/helpers' +import { chainflipService } from '../utils/chainflipService' +import { getEvmTxFees } from '../txFeeHelpers/evmTxFees/getEvmTxFees' +import { getUtxoTxFees } from '../txFeeHelpers/utxoTxFees/getUtxoTxFees' -const CHAINFLIP_REGULAR_QUOTE = 'regular'; -const CHAINFLIP_DCA_QUOTE = 'dca'; -const CHAINFLIP_BAAS_COMMISSION = 5; +const CHAINFLIP_REGULAR_QUOTE = 'regular' +const CHAINFLIP_DCA_QUOTE = 'dca' +const CHAINFLIP_BAAS_COMMISSION = 5 -export const getChainflipTradeQuote = async ( +export const getTradeQuote = async ( input: GetTradeQuoteInput, deps: SwapperDeps, ): Promise> => { @@ -89,24 +89,24 @@ export const getChainflipTradeQuote = async ( ) } - const sellChainflipChainKey = `${sellAsset.symbol.toLowerCase()}.${chainIdToChainflipNetwork[sellAsset.chainId as KnownChainIds]}`; - const buyChainflipChainKey = `${buyAsset.symbol.toLowerCase()}.${chainIdToChainflipNetwork[buyAsset.chainId as KnownChainIds]}`; + const sellChainflipChainKey = `${sellAsset.symbol.toLowerCase()}.${chainIdToChainflipNetwork[sellAsset.chainId as KnownChainIds]}` + const buyChainflipChainKey = `${buyAsset.symbol.toLowerCase()}.${chainIdToChainflipNetwork[buyAsset.chainId as KnownChainIds]}` const brokerUrl = deps.config.REACT_APP_CHAINFLIP_API_URL - const apiKey = deps.config.REACT_APP_CHAINFLIP_API_KEY; + const apiKey = deps.config.REACT_APP_CHAINFLIP_API_KEY // Subtract the BaaS fee to end up at the final displayed commissionBps - let serviceCommission = parseInt(commissionBps) - CHAINFLIP_BAAS_COMMISSION; + let serviceCommission = parseInt(commissionBps) - CHAINFLIP_BAAS_COMMISSION if (serviceCommission < 0) - serviceCommission = 0; + serviceCommission = 0 const maybeQuoteResponse = await chainflipService.get( `${brokerUrl}/quotes-native?apiKey=${apiKey}&sourceAsset=${sellChainflipChainKey}&destinationAsset=${buyChainflipChainKey}&amount=${sellAmount}&commissionBps=${serviceCommission}`, - ); + ) if (maybeQuoteResponse.isErr()) { - const error = maybeQuoteResponse.unwrapErr(); - const cause = error.cause as AxiosError; + const error = maybeQuoteResponse.unwrapErr() + const cause = error.cause as AxiosError if (cause.message.includes('code 400') && cause.response!.data.detail.includes('Amount outside asset bounds')) { return Err( @@ -127,24 +127,22 @@ export const getChainflipTradeQuote = async ( const { data: quoteResponse } = maybeQuoteResponse.unwrap() - const defaultSlippage = getDefaultSlippageDecimalPercentageForSwapper(SwapperName.Chainflip); - const getNetworkFeeCryptoBaseUnit = async () => { - const { chainNamespace } = fromAssetId(sellAsset.assetId); + const { chainNamespace } = fromAssetId(sellAsset.assetId) switch (chainNamespace) { case CHAIN_NAMESPACE.Evm: { - const sellAdapter = deps.assertGetEvmChainAdapter(sellAsset.chainId); + const sellAdapter = deps.assertGetEvmChainAdapter(sellAsset.chainId) return await getEvmTxFees({ adapter: sellAdapter, supportsEIP1559: (input as GetEvmTradeQuoteInput).supportsEIP1559, sendAsset: sellChainflipChainKey - }); + }) } case CHAIN_NAMESPACE.Utxo: { const sellAdapter = deps.assertGetUtxoChainAdapter(sellAsset.chainId) - const publicKey = (input as GetUtxoTradeQuoteInput).xpub!; + const publicKey = (input as GetUtxoTradeQuoteInput).xpub! return await getUtxoTxFees({ sellAmountCryptoBaseUnit: sellAmount, sellAdapter, @@ -154,31 +152,31 @@ export const getChainflipTradeQuote = async ( case CHAIN_NAMESPACE.Solana: { // TODO: Solana gas calc - return undefined; + return undefined } } - return undefined; + return undefined } const getFeeAsset = (fee: ChainflipBaasQuoteQuoteFee) => { if (fee.type === 'ingress' || fee.type === 'boost') - return sellAsset; + return sellAsset if (fee.type === 'egress') - return buyAsset; + return buyAsset if (fee.type === 'liquidity' && fee.asset == sellChainflipChainKey) - return sellAsset; + return sellAsset if (fee.type === 'liquidity' && fee.asset == buyChainflipChainKey) - return buyAsset; + return buyAsset if (fee.type === 'liquidity' && fee.asset == "usdc.eth") - return usdcAsset; + return usdcAsset if (fee.type === "network") - return usdcAsset; + return usdcAsset } const getProtocolFees = (singleQuoteResponse: ChainflipBaasQuoteQuote) => { @@ -186,7 +184,7 @@ export const getChainflipTradeQuote = async ( for (const fee of singleQuoteResponse.includedFees!) { if (fee.type === "broker") - continue; + continue const asset = getFeeAsset(fee)! if (!(asset.assetId in protocolFees)) { @@ -198,10 +196,10 @@ export const getChainflipTradeQuote = async ( } protocolFees[asset.assetId].amountCryptoBaseUnit = - (BigInt(protocolFees[asset.assetId].amountCryptoBaseUnit) + BigInt(fee.amountNative!)).toString(); + (BigInt(protocolFees[asset.assetId].amountCryptoBaseUnit) + BigInt(fee.amountNative!)).toString() } - return protocolFees; + return protocolFees } const getQuoteRate = (sellAmountCryptoBaseUnit: string, buyAmountCryptoBaseUnit: string) => { @@ -210,29 +208,29 @@ export const getChainflipTradeQuote = async ( buyAmountCryptoBaseUnit: buyAmountCryptoBaseUnit, sellAsset, buyAsset, - }); + }) } const getSwapSource = (swapType: string | undefined, isBoosted: boolean) => { return swapType === CHAINFLIP_REGULAR_QUOTE ? isBoosted ? CHAINFLIP_BOOST_SWAP_SOURCE : CHAINFLIP_SWAP_SOURCE - : isBoosted ? CHAINFLIP_DCA_BOOST_SWAP_SOURCE : CHAINFLIP_DCA_SWAP_SOURCE; + : isBoosted ? CHAINFLIP_DCA_BOOST_SWAP_SOURCE : CHAINFLIP_DCA_SWAP_SOURCE } - - const quotes = []; + + const quotes: TradeQuote[] = [] for (const singleQuoteResponse of quoteResponse) { - const isStreaming = singleQuoteResponse.type === CHAINFLIP_DCA_QUOTE; + const isStreaming = singleQuoteResponse.type === CHAINFLIP_DCA_QUOTE if (isStreaming && !deps.config.REACT_APP_FEATURE_CHAINFLIP_DCA) { // Streaming swaps are not enabled yet - continue; + continue } if (singleQuoteResponse.boostQuote) { const boostRate = getQuoteRate( singleQuoteResponse.boostQuote.ingressAmountNative!, - singleQuoteResponse.boostQuote.egressAmountNative!); + singleQuoteResponse.boostQuote.egressAmountNative!) const boostTradeQuote: TradeQuote = { id: uuid(), @@ -241,7 +239,7 @@ export const getChainflipTradeQuote = async ( potentialAffiliateBps: commissionBps, affiliateBps: commissionBps, isStreaming: isStreaming, - slippageTolerancePercentageDecimal: defaultSlippage, + slippageTolerancePercentageDecimal: getDefaultSlippageDecimalPercentageForSwapper(SwapperName.Chainflip), steps: [ { buyAmountBeforeFeesCryptoBaseUnit: singleQuoteResponse.boostQuote.egressAmountNative!, @@ -260,14 +258,14 @@ export const getChainflipTradeQuote = async ( estimatedExecutionTimeMs: singleQuoteResponse.boostQuote.estimatedDurationSeconds! * 1000 } ] - }; + } - quotes.push(boostTradeQuote); + quotes.push(boostTradeQuote) } const rate = getQuoteRate( singleQuoteResponse.ingressAmountNative!, - singleQuoteResponse.egressAmountNative!); + singleQuoteResponse.egressAmountNative!) const tradeQuote: TradeQuote = { id: uuid(), @@ -276,7 +274,7 @@ export const getChainflipTradeQuote = async ( potentialAffiliateBps: commissionBps, affiliateBps: commissionBps, isStreaming: isStreaming, - slippageTolerancePercentageDecimal: defaultSlippage, + slippageTolerancePercentageDecimal: getDefaultSlippageDecimalPercentageForSwapper(SwapperName.Chainflip), steps: [ { buyAmountBeforeFeesCryptoBaseUnit: singleQuoteResponse.egressAmountNative!, @@ -295,10 +293,10 @@ export const getChainflipTradeQuote = async ( estimatedExecutionTimeMs: singleQuoteResponse.estimatedDurationSeconds! * 1000 } ] - }; + } - quotes.push(tradeQuote); + quotes.push(tradeQuote) } - return Ok(quotes); + return Ok(quotes) } diff --git a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts new file mode 100644 index 00000000000..a8c877ce6d5 --- /dev/null +++ b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts @@ -0,0 +1,65 @@ +import { evm } from '@shapeshiftoss/chain-adapters' +import { bn } from '@shapeshiftoss/utils' +import { fromChainId } from '@shapeshiftoss/caip' + +import type { + EvmTransactionRequest, + GetUnsignedEvmTransactionArgs +} from '../../../types' +import { isExecutableTradeQuote } from '../../../utils' + +export const getUnsignedEvmTransaction = async ({ + chainId, + from, + tradeQuote, + supportsEIP1559, + assertGetEvmChainAdapter, + //config +}: GetUnsignedEvmTransactionArgs): Promise => { + if (!isExecutableTradeQuote(tradeQuote)) throw Error('Unable to execute trade') + + // const { transactionRequest } = await buildChainflipDepositChannel() + // + // if (!transactionRequest) { + // throw Error('undefined transactionRequest') + // } + // + // const { to, value, data, gasLimit } = transactionRequest + + // TODO: Call CF to get deposit channel opened and use deposit address as "to" + const to = '' + const value = '' + const data = '' + const gasLimit = '' + + // checking values individually to keep type checker happy + if (to === undefined || value === undefined || data === undefined || gasLimit === undefined) { + const undefinedRequiredValues = [to, value, data, gasLimit].filter( + value => value === undefined, + ) + + throw Error('undefined required values in transactionRequest', { + cause: { + undefinedRequiredValues, + }, + }) + } + + const feeData = await evm.getFees({ + adapter: assertGetEvmChainAdapter(chainId), + data: data.toString(), + to, + value: bn(value.toString()).toString(), + from, + supportsEIP1559, + }) + + return { + to, + from, + value: value.toString(), + data: data.toString(), + chainId: Number(fromChainId(chainId).chainReference), + ...{ ...feeData, gasLimit: gasLimit.toString() }, + } +} \ No newline at end of file diff --git a/packages/swapper/src/swappers/ChainflipSwapper/txFeeHelpers/evmTxFees/getEvmTxFees.ts b/packages/swapper/src/swappers/ChainflipSwapper/txFeeHelpers/evmTxFees/getEvmTxFees.ts index c16138794da..ead3ab30180 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/txFeeHelpers/evmTxFees/getEvmTxFees.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/txFeeHelpers/evmTxFees/getEvmTxFees.ts @@ -1,6 +1,7 @@ import type { EvmChainAdapter } from '@shapeshiftoss/chain-adapters' import { evm } from '@shapeshiftoss/chain-adapters' -import { assetGasLimits } from '../../constants'; + +import { assetGasLimits } from '../../constants' type GetEvmTxFeesArgs = { adapter: EvmChainAdapter @@ -13,7 +14,7 @@ export const getEvmTxFees = async (args: GetEvmTxFeesArgs): Promise => { const { average } = await adapter.getGasFeeData() - const gasLimit = (args.sendAsset in assetGasLimits) ? assetGasLimits[args.sendAsset]! : '100000'; + const gasLimit = (args.sendAsset in assetGasLimits) ? assetGasLimits[args.sendAsset]! : '100000' return evm.calcNetworkFeeCryptoBaseUnit({ ...average, diff --git a/packages/swapper/src/swappers/ChainflipSwapper/txFeeHelpers/utxoTxFees/getUtxoTxFees.ts b/packages/swapper/src/swappers/ChainflipSwapper/txFeeHelpers/utxoTxFees/getUtxoTxFees.ts index 8f039036a43..f97cb30581e 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/txFeeHelpers/utxoTxFees/getUtxoTxFees.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/txFeeHelpers/utxoTxFees/getUtxoTxFees.ts @@ -15,7 +15,7 @@ export const getUtxoTxFees = async ({ }: GetUtxoTxFeesInput): Promise => { // TODO: Get Chainflip BTC vault address const getFeeDataInput: GetFeeDataInput = { - to: 'vault', + to: '', value: sellAmountCryptoBaseUnit, chainSpecific: { pubkey: publicKey }, } @@ -24,5 +24,5 @@ export const getUtxoTxFees = async ({ const feeData = feeDataOptions['fast'] - return bn(feeData.txFee).dp(0).toString(); + return bn(feeData.txFee).dp(0).toString() } diff --git a/packages/swapper/src/swappers/ChainflipSwapper/utils/helpers.ts b/packages/swapper/src/swappers/ChainflipSwapper/utils/helpers.ts index b23f7f542cb..22ae4929580 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/utils/helpers.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/utils/helpers.ts @@ -1,7 +1,7 @@ import { type ChainId, type AssetId } from '@shapeshiftoss/caip' import type { ChainflipSupportedChainId } from '../constants' -import { ChainflipSupportedChainIds, ChainflipSupportedAssetIdsByChainId } from '../constants'; +import { ChainflipSupportedChainIds, ChainflipSupportedAssetIdsByChainId } from '../constants' export const isSupportedChainId = (chainId: ChainId): chainId is ChainflipSupportedChainId => { return ChainflipSupportedChainIds.includes(chainId as ChainflipSupportedChainId) From 630f8efe4f0f366842d17f6db2a2d7695ccf7a55 Mon Sep 17 00:00:00 2001 From: David Cumps Date: Sat, 26 Oct 2024 12:03:01 +0200 Subject: [PATCH 044/127] fix: correct swapper path --- packages/swapper/src/constants.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/swapper/src/constants.ts b/packages/swapper/src/constants.ts index cc886bdad1c..2970549c431 100644 --- a/packages/swapper/src/constants.ts +++ b/packages/swapper/src/constants.ts @@ -4,7 +4,7 @@ import { arbitrumBridgeApi } from './swappers/ArbitrumBridgeSwapper/endpoints' import { arbitrumBridgeSwapper } from './swappers/ArbitrumBridgeSwapper/ArbitrumBridgeSwapper' import { ARBITRUM_BRIDGE_SUPPORTED_CHAIN_IDS } from './swappers/ArbitrumBridgeSwapper/utils/constants' -import { chainflipApi } from './swappers/ChainflipSwapper/endpoints' +import { chainflipApi } from './swappers/ChainflipSwapper/ChainflipSwapperApi' import { chainflipSwapper } from './swappers/ChainflipSwapper/ChainflipSwapper' import { CHAINFLIP_SUPPORTED_CHAIN_IDS } from './swappers/ChainflipSwapper/constants' From e931c5b12e8ec815d8f966efe81fede5e1aa6095 Mon Sep 17 00:00:00 2001 From: David Cumps Date: Mon, 28 Oct 2024 18:45:05 +0100 Subject: [PATCH 045/127] refactor: move files around --- .../src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts | 4 ++-- .../{txFeeHelpers/evmTxFees => utils}/getEvmTxFees.ts | 0 .../{txFeeHelpers/utxoTxFees => utils}/getUtxoTxFees.ts | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename packages/swapper/src/swappers/ChainflipSwapper/{txFeeHelpers/evmTxFees => utils}/getEvmTxFees.ts (100%) rename packages/swapper/src/swappers/ChainflipSwapper/{txFeeHelpers/utxoTxFees => utils}/getUtxoTxFees.ts (100%) diff --git a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts index 002f2a0b867..8a815c4db9e 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts @@ -29,8 +29,8 @@ import { import { ChainflipBaasQuoteQuote, ChainflipBaasQuoteQuoteFee } from '../models' import { isSupportedAssetId, isSupportedChainId } from '../utils/helpers' import { chainflipService } from '../utils/chainflipService' -import { getEvmTxFees } from '../txFeeHelpers/evmTxFees/getEvmTxFees' -import { getUtxoTxFees } from '../txFeeHelpers/utxoTxFees/getUtxoTxFees' +import { getEvmTxFees } from '../utils/getEvmTxFees' +import { getUtxoTxFees } from '../utils/getUtxoTxFees' const CHAINFLIP_REGULAR_QUOTE = 'regular' const CHAINFLIP_DCA_QUOTE = 'dca' diff --git a/packages/swapper/src/swappers/ChainflipSwapper/txFeeHelpers/evmTxFees/getEvmTxFees.ts b/packages/swapper/src/swappers/ChainflipSwapper/utils/getEvmTxFees.ts similarity index 100% rename from packages/swapper/src/swappers/ChainflipSwapper/txFeeHelpers/evmTxFees/getEvmTxFees.ts rename to packages/swapper/src/swappers/ChainflipSwapper/utils/getEvmTxFees.ts diff --git a/packages/swapper/src/swappers/ChainflipSwapper/txFeeHelpers/utxoTxFees/getUtxoTxFees.ts b/packages/swapper/src/swappers/ChainflipSwapper/utils/getUtxoTxFees.ts similarity index 100% rename from packages/swapper/src/swappers/ChainflipSwapper/txFeeHelpers/utxoTxFees/getUtxoTxFees.ts rename to packages/swapper/src/swappers/ChainflipSwapper/utils/getUtxoTxFees.ts From 8f4b47a2aac38f4efbd58c3b0765f9754596c5e2 Mon Sep 17 00:00:00 2001 From: David Cumps Date: Mon, 28 Oct 2024 21:51:34 +0100 Subject: [PATCH 046/127] feat: start unsigned evm tx --- .../swappers/ChainflipSwapper/constants.ts | 4 ++ .../swapperApi/getTradeQuote.ts | 16 +++-- .../swapperApi/getUnsignedEvmTransaction.ts | 62 ++++++++++++++++--- .../ChainflipSwapper/utils/getEvmTxFees.ts | 2 +- .../ChainflipSwapper/utils/helpers.ts | 34 +++++++++- 5 files changed, 100 insertions(+), 18 deletions(-) diff --git a/packages/swapper/src/swappers/ChainflipSwapper/constants.ts b/packages/swapper/src/swappers/ChainflipSwapper/constants.ts index 95a63bf2251..b28f73207ee 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/constants.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/constants.ts @@ -20,6 +20,10 @@ const BITCOIN_BTC_ASSET_ID: AssetId = 'bip122:000000000019d6689c085ae165831e93/s const SOLANA_SOL_ASSET_ID: AssetId = 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/slip44:501' const SOLANA_USDC_ASSET_ID: AssetId = 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/token:EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v' +export const CHAINFLIP_REGULAR_QUOTE = 'regular' +export const CHAINFLIP_DCA_QUOTE = 'dca' +export const CHAINFLIP_BAAS_COMMISSION = 5 + export const ChainflipSupportedChainIds = [ KnownChainIds.EthereumMainnet, KnownChainIds.ArbitrumMainnet, diff --git a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts index 8a815c4db9e..70d0a1b31f5 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts @@ -24,7 +24,10 @@ import { CHAINFLIP_DCA_SWAP_SOURCE, CHAINFLIP_SWAP_SOURCE, chainIdToChainflipNetwork, - usdcAsset + usdcAsset, + CHAINFLIP_BAAS_COMMISSION, + CHAINFLIP_REGULAR_QUOTE, + CHAINFLIP_DCA_QUOTE, } from '../constants' import { ChainflipBaasQuoteQuote, ChainflipBaasQuoteQuoteFee } from '../models' import { isSupportedAssetId, isSupportedChainId } from '../utils/helpers' @@ -32,10 +35,6 @@ import { chainflipService } from '../utils/chainflipService' import { getEvmTxFees } from '../utils/getEvmTxFees' import { getUtxoTxFees } from '../utils/getUtxoTxFees' -const CHAINFLIP_REGULAR_QUOTE = 'regular' -const CHAINFLIP_DCA_QUOTE = 'dca' -const CHAINFLIP_BAAS_COMMISSION = 5 - export const getTradeQuote = async ( input: GetTradeQuoteInput, deps: SwapperDeps, @@ -101,7 +100,12 @@ export const getTradeQuote = async ( serviceCommission = 0 const maybeQuoteResponse = await chainflipService.get( - `${brokerUrl}/quotes-native?apiKey=${apiKey}&sourceAsset=${sellChainflipChainKey}&destinationAsset=${buyChainflipChainKey}&amount=${sellAmount}&commissionBps=${serviceCommission}`, + `${brokerUrl}/quotes-native`+ + `?apiKey=${apiKey}` + + `&sourceAsset=${sellChainflipChainKey}` + + `&destinationAsset=${buyChainflipChainKey}` + + `&amount=${sellAmount}` + + `&commissionBps=${serviceCommission}`, ) if (maybeQuoteResponse.isErr()) { diff --git a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts index a8c877ce6d5..dc60a3abcf1 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts @@ -1,6 +1,8 @@ +import { AxiosError } from 'axios' import { evm } from '@shapeshiftoss/chain-adapters' import { bn } from '@shapeshiftoss/utils' import { fromChainId } from '@shapeshiftoss/caip' +import { KnownChainIds } from '@shapeshiftoss/types' import type { EvmTransactionRequest, @@ -8,30 +10,70 @@ import type { } from '../../../types' import { isExecutableTradeQuote } from '../../../utils' +import { + chainIdToChainflipNetwork, + CHAINFLIP_BAAS_COMMISSION, +} from '../constants' +import { ChainflipBaasSwapDepositAddress } from '../models' +import { chainflipService } from '../utils/chainflipService' +import { isNativeEvmAsset } from '../utils/helpers' + export const getUnsignedEvmTransaction = async ({ chainId, from, tradeQuote, supportsEIP1559, assertGetEvmChainAdapter, - //config + config }: GetUnsignedEvmTransactionArgs): Promise => { if (!isExecutableTradeQuote(tradeQuote)) throw Error('Unable to execute trade') - // const { transactionRequest } = await buildChainflipDepositChannel() - // - // if (!transactionRequest) { - // throw Error('undefined transactionRequest') - // } - // - // const { to, value, data, gasLimit } = transactionRequest + const brokerUrl = config.REACT_APP_CHAINFLIP_API_URL + const apiKey = config.REACT_APP_CHAINFLIP_API_KEY + + const step = tradeQuote.steps[0] + const sellChainflipChainKey = `${step.sellAsset.symbol.toLowerCase()}.${chainIdToChainflipNetwork[step.sellAsset.chainId as KnownChainIds]}` + const buyChainflipChainKey = `${step.buyAsset.symbol.toLowerCase()}.${chainIdToChainflipNetwork[step.buyAsset.chainId as KnownChainIds]}` + + + // Subtract the BaaS fee to end up at the final displayed commissionBps + let serviceCommission = parseInt(tradeQuote.affiliateBps) - CHAINFLIP_BAAS_COMMISSION + if (serviceCommission < 0) + serviceCommission = 0 + + const maybeSwapResponse = await chainflipService.get( + `${brokerUrl}/swap` + + `?apiKey=${apiKey}` + + `&sourceAsset=${sellChainflipChainKey}` + + `&destinationAsset=${buyChainflipChainKey}` + + `&destinationAddress=${tradeQuote.receiveAddress}` + + `&boostFee=10` + + // TODO: Calculate minprice based on tradeQuote.slippageTolerancePercentageDecimal, step.sellAmountIncludingProtocolFeesCryptoBaseUnit + // `&minimumPrice=` + + // `&refundAddress=${from}` + + // `&retryDurationInBlocks=10` + + `&commissionBps=${serviceCommission}`, + + // TODO: For DCA swaps we need to add the numberOfChunks/chunkIntervalBlocks parameters + ) + + if (maybeSwapResponse.isErr()) { + const error = maybeSwapResponse.unwrapErr() + const cause = error.cause as AxiosError + throw Error(cause.response!.data.detail); + } + const { data: swapResponse } = maybeSwapResponse.unwrap() + // TODO: Call CF to get deposit channel opened and use deposit address as "to" - const to = '' - const value = '' + const to = swapResponse.address! const data = '' const gasLimit = '' + const value = isNativeEvmAsset(step.sellAsset.assetId) + ? step.sellAmountIncludingProtocolFeesCryptoBaseUnit + : '0' + // checking values individually to keep type checker happy if (to === undefined || value === undefined || data === undefined || gasLimit === undefined) { const undefinedRequiredValues = [to, value, data, gasLimit].filter( diff --git a/packages/swapper/src/swappers/ChainflipSwapper/utils/getEvmTxFees.ts b/packages/swapper/src/swappers/ChainflipSwapper/utils/getEvmTxFees.ts index ead3ab30180..4b88d7412fb 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/utils/getEvmTxFees.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/utils/getEvmTxFees.ts @@ -1,7 +1,7 @@ import type { EvmChainAdapter } from '@shapeshiftoss/chain-adapters' import { evm } from '@shapeshiftoss/chain-adapters' -import { assetGasLimits } from '../../constants' +import { assetGasLimits } from '../constants' type GetEvmTxFeesArgs = { adapter: EvmChainAdapter diff --git a/packages/swapper/src/swappers/ChainflipSwapper/utils/helpers.ts b/packages/swapper/src/swappers/ChainflipSwapper/utils/helpers.ts index 22ae4929580..f4dde4fd28b 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/utils/helpers.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/utils/helpers.ts @@ -1,7 +1,15 @@ -import { type ChainId, type AssetId } from '@shapeshiftoss/caip' +import { + type ChainId, + type AssetId, + fromAssetId, + ethAssetId, + avalancheAssetId, + optimismAssetId, bscAssetId, polygonAssetId, gnosisAssetId, arbitrumAssetId, baseAssetId +} from '@shapeshiftoss/caip' import type { ChainflipSupportedChainId } from '../constants' import { ChainflipSupportedChainIds, ChainflipSupportedAssetIdsByChainId } from '../constants' +import {KnownChainIds} from "@shapeshiftoss/types"; export const isSupportedChainId = (chainId: ChainId): chainId is ChainflipSupportedChainId => { return ChainflipSupportedChainIds.includes(chainId as ChainflipSupportedChainId) @@ -10,3 +18,27 @@ export const isSupportedChainId = (chainId: ChainId): chainId is ChainflipSuppor export const isSupportedAssetId = (chainId: ChainId, assetId: AssetId): chainId is ChainflipSupportedChainId => { return ChainflipSupportedAssetIdsByChainId[chainId as ChainflipSupportedChainId]!.includes(assetId) } + +export const isNativeEvmAsset = (assetId: AssetId): boolean => { + const { chainId } = fromAssetId(assetId) + switch (chainId) { + case KnownChainIds.EthereumMainnet: + return assetId === ethAssetId + case KnownChainIds.AvalancheMainnet: + return assetId === avalancheAssetId + case KnownChainIds.OptimismMainnet: + return assetId === optimismAssetId + case KnownChainIds.BnbSmartChainMainnet: + return assetId === bscAssetId + case KnownChainIds.PolygonMainnet: + return assetId === polygonAssetId + case KnownChainIds.GnosisMainnet: + return assetId === gnosisAssetId + case KnownChainIds.ArbitrumMainnet: + return assetId === arbitrumAssetId + case KnownChainIds.BaseMainnet: + return assetId === baseAssetId + default: + return false + } +} \ No newline at end of file From 8662c0ded53adc830a54c81403bb4a12eca7dc4a Mon Sep 17 00:00:00 2001 From: David Cumps Date: Mon, 28 Oct 2024 21:58:36 +0100 Subject: [PATCH 047/127] chore: add todo --- .../ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts index dc60a3abcf1..0a1941b3fd9 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts @@ -87,6 +87,8 @@ export const getUnsignedEvmTransaction = async ({ }) } + // TODO: Figure out what to do here. Just a transfer() call apparently, but how? + const feeData = await evm.getFees({ adapter: assertGetEvmChainAdapter(chainId), data: data.toString(), From 3517d98978d09a934b6e23017533b5277462fd70 Mon Sep 17 00:00:00 2001 From: David Cumps Date: Mon, 28 Oct 2024 22:18:09 +0100 Subject: [PATCH 048/127] feat: add unsigned utxo --- .../ChainflipSwapper/ChainflipSwapperApi.ts | 2 + .../swapperApi/getUnsignedEvmTransaction.ts | 34 +++------ .../swapperApi/getUnsignedUtxoTransaction.ts | 76 +++++++++++++++++++ 3 files changed, 87 insertions(+), 25 deletions(-) create mode 100644 packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedUtxoTransaction.ts diff --git a/packages/swapper/src/swappers/ChainflipSwapper/ChainflipSwapperApi.ts b/packages/swapper/src/swappers/ChainflipSwapper/ChainflipSwapperApi.ts index eb2362a34f9..5ba44f02307 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/ChainflipSwapperApi.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/ChainflipSwapperApi.ts @@ -2,10 +2,12 @@ import type { SwapperApi } from '../../types' import { getTradeQuote } from './swapperApi/getTradeQuote' import { getUnsignedEvmTransaction } from './swapperApi/getUnsignedEvmTransaction' +import { getUnsignedUtxoTransaction } from './swapperApi/getUnsignedUtxoTransaction' import { checkTradeStatus } from './swapperApi/checkTradeStatus' export const chainflipApi: SwapperApi = { getTradeQuote, getUnsignedEvmTransaction, + getUnsignedUtxoTransaction, checkTradeStatus } diff --git a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts index 0a1941b3fd9..514def1deca 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts @@ -34,7 +34,6 @@ export const getUnsignedEvmTransaction = async ({ const step = tradeQuote.steps[0] const sellChainflipChainKey = `${step.sellAsset.symbol.toLowerCase()}.${chainIdToChainflipNetwork[step.sellAsset.chainId as KnownChainIds]}` const buyChainflipChainKey = `${step.buyAsset.symbol.toLowerCase()}.${chainIdToChainflipNetwork[step.buyAsset.chainId as KnownChainIds]}` - // Subtract the BaaS fee to end up at the final displayed commissionBps let serviceCommission = parseInt(tradeQuote.affiliateBps) - CHAINFLIP_BAAS_COMMISSION @@ -65,45 +64,30 @@ export const getUnsignedEvmTransaction = async ({ const { data: swapResponse } = maybeSwapResponse.unwrap() - // TODO: Call CF to get deposit channel opened and use deposit address as "to" - const to = swapResponse.address! - const data = '' - const gasLimit = '' - + const depositAddress = swapResponse.address! const value = isNativeEvmAsset(step.sellAsset.assetId) ? step.sellAmountIncludingProtocolFeesCryptoBaseUnit : '0' - // checking values individually to keep type checker happy - if (to === undefined || value === undefined || data === undefined || gasLimit === undefined) { - const undefinedRequiredValues = [to, value, data, gasLimit].filter( - value => value === undefined, - ) - - throw Error('undefined required values in transactionRequest', { - cause: { - undefinedRequiredValues, - }, - }) - } - // TODO: Figure out what to do here. Just a transfer() call apparently, but how? + const adapter = assertGetEvmChainAdapter(chainId) + //adapter.buildSendTransaction() const feeData = await evm.getFees({ - adapter: assertGetEvmChainAdapter(chainId), - data: data.toString(), - to, + adapter: adapter, + data: '', + to: depositAddress, value: bn(value.toString()).toString(), from, supportsEIP1559, }) return { - to, + to: depositAddress, from, value: value.toString(), - data: data.toString(), + data: '', chainId: Number(fromChainId(chainId).chainReference), - ...{ ...feeData, gasLimit: gasLimit.toString() }, + ...{ ...feeData }, } } \ No newline at end of file diff --git a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedUtxoTransaction.ts b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedUtxoTransaction.ts new file mode 100644 index 00000000000..cfa2b9e5937 --- /dev/null +++ b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedUtxoTransaction.ts @@ -0,0 +1,76 @@ +import { AxiosError } from 'axios'; +import type { BTCSignTx } from '@shapeshiftoss/hdwallet-core' +import { KnownChainIds } from '@shapeshiftoss/types'; + +import { + CHAINFLIP_BAAS_COMMISSION, + chainIdToChainflipNetwork +} from '../constants'; +import { chainflipService } from '../utils/chainflipService'; +import { ChainflipBaasSwapDepositAddress } from '../models'; + +import type { + GetUnsignedUtxoTransactionArgs, + UtxoFeeData +} from '../../../types' +import { isExecutableTradeQuote } from '../../../utils' + +export const getUnsignedUtxoTransaction = async ({ + tradeQuote, + xpub, + accountType, + assertGetUtxoChainAdapter, + config, +}: GetUnsignedUtxoTransactionArgs): Promise => { + if (!isExecutableTradeQuote(tradeQuote)) throw Error('Unable to execute trade') + + const brokerUrl = config.REACT_APP_CHAINFLIP_API_URL + const apiKey = config.REACT_APP_CHAINFLIP_API_KEY + + const step = tradeQuote.steps[0] + const sellChainflipChainKey = `${step.sellAsset.symbol.toLowerCase()}.${chainIdToChainflipNetwork[step.sellAsset.chainId as KnownChainIds]}` + const buyChainflipChainKey = `${step.buyAsset.symbol.toLowerCase()}.${chainIdToChainflipNetwork[step.buyAsset.chainId as KnownChainIds]}` + + // Subtract the BaaS fee to end up at the final displayed commissionBps + let serviceCommission = parseInt(tradeQuote.affiliateBps) - CHAINFLIP_BAAS_COMMISSION + if (serviceCommission < 0) + serviceCommission = 0 + + const maybeSwapResponse = await chainflipService.get( + `${brokerUrl}/swap` + + `?apiKey=${apiKey}` + + `&sourceAsset=${sellChainflipChainKey}` + + `&destinationAsset=${buyChainflipChainKey}` + + `&destinationAddress=${tradeQuote.receiveAddress}` + + `&boostFee=10` + + // TODO: Calculate minprice based on tradeQuote.slippageTolerancePercentageDecimal, step.sellAmountIncludingProtocolFeesCryptoBaseUnit + // `&minimumPrice=` + + // `&refundAddress=${from}` + + // `&retryDurationInBlocks=10` + + `&commissionBps=${serviceCommission}`, + + // TODO: For DCA swaps we need to add the numberOfChunks/chunkIntervalBlocks parameters + ) + + if (maybeSwapResponse.isErr()) { + const error = maybeSwapResponse.unwrapErr() + const cause = error.cause as AxiosError + throw Error(cause.response!.data.detail); + } + + const { data: swapResponse } = maybeSwapResponse.unwrap() + + const depositAddress = swapResponse.address! + + return assertGetUtxoChainAdapter(step.sellAsset.chainId).buildSendApiTransaction({ + value: step.sellAmountIncludingProtocolFeesCryptoBaseUnit, + xpub: xpub!, + to: depositAddress, + accountNumber: step.accountNumber, + skipToAddressValidation: true, + chainSpecific: { + accountType, + satoshiPerByte: (step.feeData.chainSpecific as UtxoFeeData).satsPerByte, + }, + }) +} From ae2870921b2647cc8272b8d130defa0564192332 Mon Sep 17 00:00:00 2001 From: David Cumps Date: Mon, 28 Oct 2024 22:19:17 +0100 Subject: [PATCH 049/127] feat: add executeUtxoTransaction --- .../swappers/ChainflipSwapper/ChainflipSwapper.ts | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/packages/swapper/src/swappers/ChainflipSwapper/ChainflipSwapper.ts b/packages/swapper/src/swappers/ChainflipSwapper/ChainflipSwapper.ts index 48a4eff09a1..d1b5947e44f 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/ChainflipSwapper.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/ChainflipSwapper.ts @@ -1,7 +1,12 @@ import type { AssetId } from '@shapeshiftoss/caip' import type { Asset } from '@shapeshiftoss/types' +import type { BTCSignTx } from '@shapeshiftoss/hdwallet-core' -import type { BuyAssetBySellIdInput, Swapper } from '../../types' +import type { + BuyAssetBySellIdInput, + Swapper, + UtxoTransactionExecutionProps +} from '../../types' import { executeEvmTransaction } from '../../utils' import { CHAINFLIP_SUPPORTED_CHAIN_IDS } from './constants' @@ -9,6 +14,13 @@ import { isSupportedAssetId } from './utils/helpers' export const chainflipSwapper: Swapper = { executeEvmTransaction, + + executeUtxoTransaction: async ( + txToSign: BTCSignTx, + { signAndBroadcastTransaction }: UtxoTransactionExecutionProps, + ): Promise => { + return await signAndBroadcastTransaction(txToSign) + }, filterAssetIdsBySellable: (assets: Asset[]): Promise => { return Promise.resolve( From 15a0499f6beaaa3868b89816d40be1d7f1be7f4a Mon Sep 17 00:00:00 2001 From: David Cumps Date: Mon, 28 Oct 2024 22:25:23 +0100 Subject: [PATCH 050/127] fix: check for undefined accountNumber --- .../ChainflipSwapper/swapperApi/getTradeQuote.ts | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts index 70d0a1b31f5..795dcd05686 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts @@ -48,6 +48,15 @@ export const getTradeQuote = async ( affiliateBps: commissionBps, } = input + if (accountNumber == undefined) { + return Err( + makeSwapErrorRight({ + message: `unsupported accountNumber`, + code: TradeQuoteError.UnknownError, + }), + ) + } + if (!isSupportedChainId(sellAsset.chainId)) { return Err( makeSwapErrorRight({ @@ -257,7 +266,7 @@ export const getTradeQuote = async ( source: getSwapSource(singleQuoteResponse.type, true), buyAsset: buyAsset, sellAsset: sellAsset, - accountNumber: accountNumber ?? 0, // TODO: What to pass if accountNumber is undefined? + accountNumber: accountNumber, allowanceContract: "0x0", // Chainflip does not use contracts estimatedExecutionTimeMs: singleQuoteResponse.boostQuote.estimatedDurationSeconds! * 1000 } @@ -292,7 +301,7 @@ export const getTradeQuote = async ( source: getSwapSource(singleQuoteResponse.type, false), buyAsset: buyAsset, sellAsset: sellAsset, - accountNumber: accountNumber ?? 0, // TODO: What to pass if accountNumber is undefined? + accountNumber: accountNumber, allowanceContract: "0x0", // Chainflip does not use contracts estimatedExecutionTimeMs: singleQuoteResponse.estimatedDurationSeconds! * 1000 } From c3c174519a2ccb859938d8e121f246cae5fee0fb Mon Sep 17 00:00:00 2001 From: David Cumps Date: Mon, 28 Oct 2024 22:39:54 +0100 Subject: [PATCH 051/127] wip: stuck at getUnsignedEvmTransaction --- .../swapperApi/getUnsignedEvmTransaction.ts | 50 +++++++++---------- 1 file changed, 24 insertions(+), 26 deletions(-) diff --git a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts index 514def1deca..d448f42a556 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts @@ -1,11 +1,12 @@ import { AxiosError } from 'axios' import { evm } from '@shapeshiftoss/chain-adapters' import { bn } from '@shapeshiftoss/utils' -import { fromChainId } from '@shapeshiftoss/caip' +import { fromChainId, fromAssetId } from '@shapeshiftoss/caip' import { KnownChainIds } from '@shapeshiftoss/types' -import type { +import type { EvmTransactionRequest, + GetEvmTradeQuoteInput, GetUnsignedEvmTransactionArgs } from '../../../types' import { isExecutableTradeQuote } from '../../../utils' @@ -16,7 +17,7 @@ import { } from '../constants' import { ChainflipBaasSwapDepositAddress } from '../models' import { chainflipService } from '../utils/chainflipService' -import { isNativeEvmAsset } from '../utils/helpers' +import { getEvmTxFees } from "../utils/getEvmTxFees"; export const getUnsignedEvmTransaction = async ({ chainId, @@ -65,29 +66,26 @@ export const getUnsignedEvmTransaction = async ({ const { data: swapResponse } = maybeSwapResponse.unwrap() const depositAddress = swapResponse.address! - const value = isNativeEvmAsset(step.sellAsset.assetId) - ? step.sellAmountIncludingProtocolFeesCryptoBaseUnit - : '0' + const { assetReference } = fromAssetId(step.sellAsset.assetId) - // TODO: Figure out what to do here. Just a transfer() call apparently, but how? - const adapter = assertGetEvmChainAdapter(chainId) - //adapter.buildSendTransaction() + throw Error('not yet implemented') - const feeData = await evm.getFees({ - adapter: adapter, - data: '', - to: depositAddress, - value: bn(value.toString()).toString(), - from, - supportsEIP1559, - }) - - return { - to: depositAddress, - from, - value: value.toString(), - data: '', - chainId: Number(fromChainId(chainId).chainReference), - ...{ ...feeData }, - } + // TODO: Figure out what to do here. Just a transfer() call apparently, but how? + // const adapter = assertGetEvmChainAdapter(chainId) + // + // const fees = await getEvmTxFees({ + // adapter: adapter, + // supportsEIP1559: supportsEIP1559, + // sendAsset: sellChainflipChainKey + // }) + // + // // TODO: Check what this does when you want to swap ETH + // return adapter.buildSendTransaction({ + // to: depositAddress, + // from: from, + // value: step.sellAmountIncludingProtocolFeesCryptoBaseUnit, + // wallet: null, // TODO: Where to get this? + // accountNumber: step.accountNumber, + // contractAddress: assetReference + // }) } \ No newline at end of file From 4a227c50fff82e06d89abe3174d4716f55af7630 Mon Sep 17 00:00:00 2001 From: David Cumps Date: Mon, 28 Oct 2024 23:39:40 +0100 Subject: [PATCH 052/127] refactor: move to buildSendApiTransaction to get rid of wallet --- .../swapperApi/getUnsignedEvmTransaction.ts | 49 +++++++++---------- 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts index d448f42a556..da58f86a668 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts @@ -1,19 +1,16 @@ import { AxiosError } from 'axios' -import { evm } from '@shapeshiftoss/chain-adapters' -import { bn } from '@shapeshiftoss/utils' -import { fromChainId, fromAssetId } from '@shapeshiftoss/caip' +import { fromAssetId } from '@shapeshiftoss/caip' import { KnownChainIds } from '@shapeshiftoss/types' import type { EvmTransactionRequest, - GetEvmTradeQuoteInput, GetUnsignedEvmTransactionArgs } from '../../../types' import { isExecutableTradeQuote } from '../../../utils' import { chainIdToChainflipNetwork, - CHAINFLIP_BAAS_COMMISSION, + CHAINFLIP_BAAS_COMMISSION, assetGasLimits, } from '../constants' import { ChainflipBaasSwapDepositAddress } from '../models' import { chainflipService } from '../utils/chainflipService' @@ -68,24 +65,26 @@ export const getUnsignedEvmTransaction = async ({ const depositAddress = swapResponse.address! const { assetReference } = fromAssetId(step.sellAsset.assetId) - throw Error('not yet implemented') - - // TODO: Figure out what to do here. Just a transfer() call apparently, but how? - // const adapter = assertGetEvmChainAdapter(chainId) - // - // const fees = await getEvmTxFees({ - // adapter: adapter, - // supportsEIP1559: supportsEIP1559, - // sendAsset: sellChainflipChainKey - // }) - // - // // TODO: Check what this does when you want to swap ETH - // return adapter.buildSendTransaction({ - // to: depositAddress, - // from: from, - // value: step.sellAmountIncludingProtocolFeesCryptoBaseUnit, - // wallet: null, // TODO: Where to get this? - // accountNumber: step.accountNumber, - // contractAddress: assetReference - // }) + const adapter = assertGetEvmChainAdapter(chainId) + + const fees = await getEvmTxFees({ + adapter: adapter, + supportsEIP1559: supportsEIP1559, + sendAsset: sellChainflipChainKey + }) + + // TODO: Check what this does when you want to swap ETH + // TODO: How to go from ETHSignTx to EvmTransactionRequest? + return adapter.buildSendApiTransaction({ + to: depositAddress, + from: from, + value: step.sellAmountIncludingProtocolFeesCryptoBaseUnit, + accountNumber: step.accountNumber, + chainSpecific: { + gasLimit: (sellChainflipChainKey in assetGasLimits) ? assetGasLimits[sellChainflipChainKey]! : '100000', + contractAddress: assetReference, + maxFeePerGas: '0', // TODO: Where to get this and maxPriorityFeePerGas? + maxPriorityFeePerGas: '0', + } + }) } \ No newline at end of file From 22372ed9d2dcb7e8d4eb6558d8d7544aec83dd95 Mon Sep 17 00:00:00 2001 From: David Cumps Date: Mon, 28 Oct 2024 23:49:22 +0100 Subject: [PATCH 053/127] feat: estimate maxFeePerGas --- .../swapperApi/getUnsignedEvmTransaction.ts | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts index da58f86a668..5983e5246bc 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts @@ -1,6 +1,7 @@ import { AxiosError } from 'axios' import { fromAssetId } from '@shapeshiftoss/caip' import { KnownChainIds } from '@shapeshiftoss/types' +import { getFees } from "@shapeshiftoss/chain-adapters/dist/evm/utils"; import type { EvmTransactionRequest, @@ -14,7 +15,6 @@ import { } from '../constants' import { ChainflipBaasSwapDepositAddress } from '../models' import { chainflipService } from '../utils/chainflipService' -import { getEvmTxFees } from "../utils/getEvmTxFees"; export const getUnsignedEvmTransaction = async ({ chainId, @@ -67,10 +67,14 @@ export const getUnsignedEvmTransaction = async ({ const adapter = assertGetEvmChainAdapter(chainId) - const fees = await getEvmTxFees({ + // TODO: Are these the correct params for data and value? + const fees = await getFees({ adapter: adapter, - supportsEIP1559: supportsEIP1559, - sendAsset: sellChainflipChainKey + data: '', + to: depositAddress, + value: step.sellAmountIncludingProtocolFeesCryptoBaseUnit, + from: from, + supportsEIP1559: supportsEIP1559 }) // TODO: Check what this does when you want to swap ETH @@ -83,8 +87,8 @@ export const getUnsignedEvmTransaction = async ({ chainSpecific: { gasLimit: (sellChainflipChainKey in assetGasLimits) ? assetGasLimits[sellChainflipChainKey]! : '100000', contractAddress: assetReference, - maxFeePerGas: '0', // TODO: Where to get this and maxPriorityFeePerGas? - maxPriorityFeePerGas: '0', + maxFeePerGas: fees.maxFeePerGas!, + maxPriorityFeePerGas: fees.maxPriorityFeePerGas!, } }) } \ No newline at end of file From 0c309d4460a0e45a95a9593725835b823d2b6721 Mon Sep 17 00:00:00 2001 From: David Cumps Date: Mon, 28 Oct 2024 23:51:52 +0100 Subject: [PATCH 054/127] style: quotes --- .../ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts index 5983e5246bc..6d7c358cf93 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts @@ -1,7 +1,7 @@ import { AxiosError } from 'axios' import { fromAssetId } from '@shapeshiftoss/caip' import { KnownChainIds } from '@shapeshiftoss/types' -import { getFees } from "@shapeshiftoss/chain-adapters/dist/evm/utils"; +import { getFees } from '@shapeshiftoss/chain-adapters/dist/evm/utils' import type { EvmTransactionRequest, From 39972457c7d9a010fd9e13e4762a07a642439ebc Mon Sep 17 00:00:00 2001 From: David Cumps Date: Tue, 29 Oct 2024 00:10:24 +0100 Subject: [PATCH 055/127] refactor: add getGasLimit --- .../swapperApi/getUnsignedEvmTransaction.ts | 5 +++-- .../src/swappers/ChainflipSwapper/utils/getEvmTxFees.ts | 4 ++-- .../src/swappers/ChainflipSwapper/utils/helpers.ts | 8 ++++++-- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts index 6d7c358cf93..25dd54c87da 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts @@ -11,10 +11,11 @@ import { isExecutableTradeQuote } from '../../../utils' import { chainIdToChainflipNetwork, - CHAINFLIP_BAAS_COMMISSION, assetGasLimits, + CHAINFLIP_BAAS_COMMISSION } from '../constants' import { ChainflipBaasSwapDepositAddress } from '../models' import { chainflipService } from '../utils/chainflipService' +import { getGasLimit } from '../utils/helpers' export const getUnsignedEvmTransaction = async ({ chainId, @@ -85,7 +86,7 @@ export const getUnsignedEvmTransaction = async ({ value: step.sellAmountIncludingProtocolFeesCryptoBaseUnit, accountNumber: step.accountNumber, chainSpecific: { - gasLimit: (sellChainflipChainKey in assetGasLimits) ? assetGasLimits[sellChainflipChainKey]! : '100000', + gasLimit: getGasLimit(sellChainflipChainKey), contractAddress: assetReference, maxFeePerGas: fees.maxFeePerGas!, maxPriorityFeePerGas: fees.maxPriorityFeePerGas!, diff --git a/packages/swapper/src/swappers/ChainflipSwapper/utils/getEvmTxFees.ts b/packages/swapper/src/swappers/ChainflipSwapper/utils/getEvmTxFees.ts index 4b88d7412fb..38dd9bf99ed 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/utils/getEvmTxFees.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/utils/getEvmTxFees.ts @@ -1,7 +1,7 @@ import type { EvmChainAdapter } from '@shapeshiftoss/chain-adapters' import { evm } from '@shapeshiftoss/chain-adapters' -import { assetGasLimits } from '../constants' +import { getGasLimit } from './helpers' type GetEvmTxFeesArgs = { adapter: EvmChainAdapter @@ -14,7 +14,7 @@ export const getEvmTxFees = async (args: GetEvmTxFeesArgs): Promise => { const { average } = await adapter.getGasFeeData() - const gasLimit = (args.sendAsset in assetGasLimits) ? assetGasLimits[args.sendAsset]! : '100000' + const gasLimit = getGasLimit(args.sendAsset) return evm.calcNetworkFeeCryptoBaseUnit({ ...average, diff --git a/packages/swapper/src/swappers/ChainflipSwapper/utils/helpers.ts b/packages/swapper/src/swappers/ChainflipSwapper/utils/helpers.ts index f4dde4fd28b..7af24df577f 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/utils/helpers.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/utils/helpers.ts @@ -6,10 +6,10 @@ import { avalancheAssetId, optimismAssetId, bscAssetId, polygonAssetId, gnosisAssetId, arbitrumAssetId, baseAssetId } from '@shapeshiftoss/caip' +import { KnownChainIds } from "@shapeshiftoss/types"; -import type { ChainflipSupportedChainId } from '../constants' +import { assetGasLimits, ChainflipSupportedChainId } from '../constants' import { ChainflipSupportedChainIds, ChainflipSupportedAssetIdsByChainId } from '../constants' -import {KnownChainIds} from "@shapeshiftoss/types"; export const isSupportedChainId = (chainId: ChainId): chainId is ChainflipSupportedChainId => { return ChainflipSupportedChainIds.includes(chainId as ChainflipSupportedChainId) @@ -19,6 +19,10 @@ export const isSupportedAssetId = (chainId: ChainId, assetId: AssetId): chainId return ChainflipSupportedAssetIdsByChainId[chainId as ChainflipSupportedChainId]!.includes(assetId) } +export const getGasLimit = (chainflipAsset: string) => { + return (chainflipAsset in assetGasLimits) ? assetGasLimits[chainflipAsset]! : '100000' +} + export const isNativeEvmAsset = (assetId: AssetId): boolean => { const { chainId } = fromAssetId(assetId) switch (chainId) { From 2cce1dbb1aad422d7336786f2eb98660914a9849 Mon Sep 17 00:00:00 2001 From: David Cumps Date: Tue, 29 Oct 2024 00:16:14 +0100 Subject: [PATCH 056/127] feat: use getErc20Data to get data --- .../swapper/src/swappers/ChainflipSwapper/constants.ts | 1 + .../swapperApi/getUnsignedEvmTransaction.ts | 10 +++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/packages/swapper/src/swappers/ChainflipSwapper/constants.ts b/packages/swapper/src/swappers/ChainflipSwapper/constants.ts index b28f73207ee..d6a88780fa5 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/constants.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/constants.ts @@ -47,6 +47,7 @@ export const chainIdToChainflipNetwork: Partial> = [KnownChainIds.SolanaMainnet]: 'sol', } +// TODO: Verify with chainflip if this are the correct values export const assetGasLimits: Partial> = { ['eth.eth']: '34000', ['flip.eth']: '52000', diff --git a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts index 25dd54c87da..05d1f1c79fb 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts @@ -1,7 +1,8 @@ import { AxiosError } from 'axios' +import { toHex } from 'viem'; import { fromAssetId } from '@shapeshiftoss/caip' import { KnownChainIds } from '@shapeshiftoss/types' -import { getFees } from '@shapeshiftoss/chain-adapters/dist/evm/utils' +import { getErc20Data, getFees } from '@shapeshiftoss/chain-adapters/dist/evm/utils' import type { EvmTransactionRequest, @@ -65,20 +66,19 @@ export const getUnsignedEvmTransaction = async ({ const depositAddress = swapResponse.address! const { assetReference } = fromAssetId(step.sellAsset.assetId) + const isTokenSend = !!assetReference const adapter = assertGetEvmChainAdapter(chainId) - // TODO: Are these the correct params for data and value? const fees = await getFees({ adapter: adapter, - data: '', to: depositAddress, - value: step.sellAmountIncludingProtocolFeesCryptoBaseUnit, from: from, + value: toHex(isTokenSend ? 0n : BigInt(step.sellAmountIncludingProtocolFeesCryptoBaseUnit)), + data: (await getErc20Data(depositAddress, step.sellAmountIncludingProtocolFeesCryptoBaseUnit, assetReference)), supportsEIP1559: supportsEIP1559 }) - // TODO: Check what this does when you want to swap ETH // TODO: How to go from ETHSignTx to EvmTransactionRequest? return adapter.buildSendApiTransaction({ to: depositAddress, From 5626b31ea4fa1ae32e833be0da25ebf2781be8f5 Mon Sep 17 00:00:00 2001 From: David Cumps Date: Tue, 29 Oct 2024 00:24:36 +0100 Subject: [PATCH 057/127] feat: return signing request --- .../swapperApi/getUnsignedEvmTransaction.ts | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts index 05d1f1c79fb..e891fcad299 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts @@ -1,6 +1,6 @@ import { AxiosError } from 'axios' import { toHex } from 'viem'; -import { fromAssetId } from '@shapeshiftoss/caip' +import {fromAssetId, fromChainId} from '@shapeshiftoss/caip' import { KnownChainIds } from '@shapeshiftoss/types' import { getErc20Data, getFees } from '@shapeshiftoss/chain-adapters/dist/evm/utils' @@ -79,8 +79,7 @@ export const getUnsignedEvmTransaction = async ({ supportsEIP1559: supportsEIP1559 }) - // TODO: How to go from ETHSignTx to EvmTransactionRequest? - return adapter.buildSendApiTransaction({ + const tx = await adapter.buildSendApiTransaction({ to: depositAddress, from: from, value: step.sellAmountIncludingProtocolFeesCryptoBaseUnit, @@ -92,4 +91,16 @@ export const getUnsignedEvmTransaction = async ({ maxPriorityFeePerGas: fees.maxPriorityFeePerGas!, } }) + + return { + chainId: Number(fromChainId(chainId).chainReference), + data: tx.data, + to: tx.to, + from: from, + value: tx.value, + gasLimit: tx.gasLimit, + maxFeePerGas: tx.maxFeePerGas, + maxPriorityFeePerGas: tx.maxPriorityFeePerGas, + gasPrice: tx.gasPrice + } } \ No newline at end of file From 5b4a64dc7dc79f7ba1c228743f86723fa018a427 Mon Sep 17 00:00:00 2001 From: David Cumps Date: Tue, 29 Oct 2024 00:42:46 +0100 Subject: [PATCH 058/127] fix: no need for toHex --- .../ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts index e891fcad299..a5a4c850fc7 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts @@ -1,6 +1,5 @@ import { AxiosError } from 'axios' -import { toHex } from 'viem'; -import {fromAssetId, fromChainId} from '@shapeshiftoss/caip' +import { fromAssetId, fromChainId } from '@shapeshiftoss/caip' import { KnownChainIds } from '@shapeshiftoss/types' import { getErc20Data, getFees } from '@shapeshiftoss/chain-adapters/dist/evm/utils' @@ -74,7 +73,7 @@ export const getUnsignedEvmTransaction = async ({ adapter: adapter, to: depositAddress, from: from, - value: toHex(isTokenSend ? 0n : BigInt(step.sellAmountIncludingProtocolFeesCryptoBaseUnit)), + value: (isTokenSend ? 0n : BigInt(step.sellAmountIncludingProtocolFeesCryptoBaseUnit)).toString(), data: (await getErc20Data(depositAddress, step.sellAmountIncludingProtocolFeesCryptoBaseUnit, assetReference)), supportsEIP1559: supportsEIP1559 }) From f69ae34eacc0cb374b7fac969142656c9c2f1ade Mon Sep 17 00:00:00 2001 From: David Cumps Date: Tue, 29 Oct 2024 00:53:43 +0100 Subject: [PATCH 059/127] chore: add slippage reference code --- .../swapperApi/getUnsignedEvmTransaction.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts index a5a4c850fc7..ca17b70e3cd 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts @@ -46,12 +46,19 @@ export const getUnsignedEvmTransaction = async ({ `&destinationAsset=${buyChainflipChainKey}` + `&destinationAddress=${tradeQuote.receiveAddress}` + `&boostFee=10` + - // TODO: Calculate minprice based on tradeQuote.slippageTolerancePercentageDecimal, step.sellAmountIncludingProtocolFeesCryptoBaseUnit + // TODO: Calculate minprice based on tradeQuote.slippageTolerancePercentageDecimal, step.sellAmountIncludingProtocolFeesCryptoBaseUnit, step.buyAmountAfterFeesCryptoBaseUnit // `&minimumPrice=` + // `&refundAddress=${from}` + // `&retryDurationInBlocks=10` + `&commissionBps=${serviceCommission}`, + // TODO: Below is the reference code of Chainflip to calculate the minPrice parameter + // const tolerance = new BigNumber(params.slippageTolerancePercent); + // const estimatedPrice = new BigNumber(quote.estimatedPrice); + // minPrice = estimatedPrice + // .times(new BigNumber(100).minus(tolerance).dividedBy(100)) + // .toFixed(assetConstants[destAsset].decimals); + // TODO: For DCA swaps we need to add the numberOfChunks/chunkIntervalBlocks parameters ) From 4924c1687964536c031e9bc9ba2788b046011542 Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Thu, 31 Oct 2024 08:21:50 +0900 Subject: [PATCH 060/127] feat: lint and cleanup some --- .env.base | 3 +- packages/swapper/src/constants.ts | 19 +- .../ChainflipSwapper/ChainflipSwapper.ts | 11 +- .../ChainflipSwapper/ChainflipSwapperApi.ts | 5 +- .../swappers/ChainflipSwapper/constants.ts | 49 ++-- .../swapperApi/checkTradeStatus.ts | 8 +- .../swapperApi/getTradeQuote.ts | 217 ++++++++++-------- .../swapperApi/getUnsignedEvmTransaction.ts | 79 ++++--- .../swapperApi/getUnsignedUtxoTransaction.ts | 58 +++-- .../utils/chainflipService.ts | 19 +- .../ChainflipSwapper/utils/getEvmTxFees.ts | 6 +- .../ChainflipSwapper/utils/getUtxoTxFees.ts | 10 +- .../ChainflipSwapper/utils/helpers.ts | 36 ++- packages/swapper/src/types.ts | 4 +- react-app-rewired/headers/csps/chainflip.ts | 4 +- .../components/SwapperIcon/SwapperIcon.tsx | 2 +- src/state/helpers.ts | 28 +-- 17 files changed, 289 insertions(+), 269 deletions(-) diff --git a/.env.base b/.env.base index 11a052b8467..1a593d62b77 100644 --- a/.env.base +++ b/.env.base @@ -55,7 +55,6 @@ REACT_APP_ABSOLUTE_URL_PREFIX=https://app.shapeshift.com # Fetch UNI-V2 assets from Zapper REACT_APP_FEATURE_DYNAMIC_LP_ASSETS=false - # Fetch read-only assets from various providers (Zapper only for now) REACT_APP_FEATURE_READ_ONLY_ASSETS=true @@ -129,7 +128,6 @@ REACT_APP_MTPELERIN_INTEGRATION_KEY=954139b2-ef3e-4914-82ea-33192d3f43d3 REACT_APP_ONRAMPER_WIDGET_URL=https://buy.onramper.com/ REACT_APP_ONRAMPER_API_URL=https://api.onramper.com/ REACT_APP_ONRAMPER_API_KEY=pk_prod_01HWMA66BYRB2271G08XDZVVCX - # y.at REACT_APP_YAT_NODE_URL=https://a.y.at @@ -154,6 +152,7 @@ REACT_APP_COVALENT_API_KEY=ckey_2160df0b81ac46e9a642b35a5f1 REACT_APP_FEATURE_COVALENT_JAYPEGS=true # Portals + REACT_APP_PORTALS_BASE_URL=https://api.portals.fi REACT_APP_PORTALS_API_KEY=bbc3ba7e-5f2a-4a0a-bbbc-22509944686c diff --git a/packages/swapper/src/constants.ts b/packages/swapper/src/constants.ts index 2970549c431..d8e5f902bdc 100644 --- a/packages/swapper/src/constants.ts +++ b/packages/swapper/src/constants.ts @@ -1,36 +1,29 @@ import { assertUnreachable } from '@shapeshiftoss/utils' -import { arbitrumBridgeApi } from './swappers/ArbitrumBridgeSwapper/endpoints' import { arbitrumBridgeSwapper } from './swappers/ArbitrumBridgeSwapper/ArbitrumBridgeSwapper' +import { arbitrumBridgeApi } from './swappers/ArbitrumBridgeSwapper/endpoints' import { ARBITRUM_BRIDGE_SUPPORTED_CHAIN_IDS } from './swappers/ArbitrumBridgeSwapper/utils/constants' - -import { chainflipApi } from './swappers/ChainflipSwapper/ChainflipSwapperApi' import { chainflipSwapper } from './swappers/ChainflipSwapper/ChainflipSwapper' +import { chainflipApi } from './swappers/ChainflipSwapper/ChainflipSwapperApi' import { CHAINFLIP_SUPPORTED_CHAIN_IDS } from './swappers/ChainflipSwapper/constants' - -import { cowApi } from './swappers/CowSwapper/endpoints' import { cowSwapper } from './swappers/CowSwapper/CowSwapper' +import { cowApi } from './swappers/CowSwapper/endpoints' import { COW_SWAP_SUPPORTED_CHAIN_IDS } from './swappers/CowSwapper/utils/constants' - import { lifiApi } from './swappers/LifiSwapper/endpoints' import { LIFI_GET_TRADE_QUOTE_POLLING_INTERVAL, lifiSwapper, } from './swappers/LifiSwapper/LifiSwapper' import { LIFI_SUPPORTED_CHAIN_IDS } from './swappers/LifiSwapper/utils/constants' - +import { PORTALS_SUPPORTED_CHAIN_IDS } from './swappers/PortalsSwapper/constants' import { portalsApi } from './swappers/PortalsSwapper/endpoints' import { portalsSwapper } from './swappers/PortalsSwapper/PortalsSwapper' -import { PORTALS_SUPPORTED_CHAIN_IDS } from './swappers/PortalsSwapper/constants' - +import { THORCHAIN_SUPPORTED_CHAIN_IDS } from './swappers/ThorchainSwapper/constants' import { thorchainApi } from './swappers/ThorchainSwapper/endpoints' import { thorchainSwapper } from './swappers/ThorchainSwapper/ThorchainSwapper' -import { THORCHAIN_SUPPORTED_CHAIN_IDS } from './swappers/ThorchainSwapper/constants' - import { zrxApi } from './swappers/ZrxSwapper/endpoints' -import { zrxSwapper } from './swappers/ZrxSwapper/ZrxSwapper' import { ZRX_SUPPORTED_CHAIN_IDS } from './swappers/ZrxSwapper/utils/constants' - +import { zrxSwapper } from './swappers/ZrxSwapper/ZrxSwapper' import type { SupportedChainIds, Swapper, SwapperApi } from './types' import { SwapperName } from './types' import { makeSwapErrorRight } from './utils' diff --git a/packages/swapper/src/swappers/ChainflipSwapper/ChainflipSwapper.ts b/packages/swapper/src/swappers/ChainflipSwapper/ChainflipSwapper.ts index d1b5947e44f..d8a89152929 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/ChainflipSwapper.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/ChainflipSwapper.ts @@ -1,14 +1,9 @@ import type { AssetId } from '@shapeshiftoss/caip' -import type { Asset } from '@shapeshiftoss/types' import type { BTCSignTx } from '@shapeshiftoss/hdwallet-core' +import type { Asset } from '@shapeshiftoss/types' -import type { - BuyAssetBySellIdInput, - Swapper, - UtxoTransactionExecutionProps -} from '../../types' +import type { BuyAssetBySellIdInput, Swapper, UtxoTransactionExecutionProps } from '../../types' import { executeEvmTransaction } from '../../utils' - import { CHAINFLIP_SUPPORTED_CHAIN_IDS } from './constants' import { isSupportedAssetId } from './utils/helpers' @@ -21,7 +16,7 @@ export const chainflipSwapper: Swapper = { ): Promise => { return await signAndBroadcastTransaction(txToSign) }, - + filterAssetIdsBySellable: (assets: Asset[]): Promise => { return Promise.resolve( assets diff --git a/packages/swapper/src/swappers/ChainflipSwapper/ChainflipSwapperApi.ts b/packages/swapper/src/swappers/ChainflipSwapper/ChainflipSwapperApi.ts index 5ba44f02307..bd7768d1b88 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/ChainflipSwapperApi.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/ChainflipSwapperApi.ts @@ -1,13 +1,12 @@ import type { SwapperApi } from '../../types' - +import { checkTradeStatus } from './swapperApi/checkTradeStatus' import { getTradeQuote } from './swapperApi/getTradeQuote' import { getUnsignedEvmTransaction } from './swapperApi/getUnsignedEvmTransaction' import { getUnsignedUtxoTransaction } from './swapperApi/getUnsignedUtxoTransaction' -import { checkTradeStatus } from './swapperApi/checkTradeStatus' export const chainflipApi: SwapperApi = { getTradeQuote, getUnsignedEvmTransaction, getUnsignedUtxoTransaction, - checkTradeStatus + checkTradeStatus, } diff --git a/packages/swapper/src/swappers/ChainflipSwapper/constants.ts b/packages/swapper/src/swappers/ChainflipSwapper/constants.ts index d6a88780fa5..839f9ab00da 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/constants.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/constants.ts @@ -1,11 +1,9 @@ -import type { ChainId, AssetId } from '@shapeshiftoss/caip' -import { Asset, KnownChainIds } from '@shapeshiftoss/types' +import type { AssetId, ChainId } from '@shapeshiftoss/caip' +import type { Asset } from '@shapeshiftoss/types' +import { KnownChainIds } from '@shapeshiftoss/types' -import { - SupportedChainIds, - SwapperName, - SwapSource -} from '../../types' +import type { SupportedChainIds, SwapSource } from '../../types' +import { SwapperName } from '../../types' const ETHEREUM_ETH_ASSET_ID: AssetId = 'eip155:1/slip44:60' const ETHEREUM_FLIP_ASSET_ID: AssetId = 'eip155:1/erc20:0x826180541412d574cf1336d22c0c0a287822678a' @@ -13,12 +11,14 @@ const ETHEREUM_USDC_ASSET_ID: AssetId = 'eip155:1/erc20:0xa0b86991c6218b36c1d19d const ETHEREUM_USDT_ASSET_ID: AssetId = 'eip155:1/erc20:0xdac17f958d2ee523a2206206994597c13d831ec7' const ARBITRUM_ETH_ASSET_ID: AssetId = 'eip155:42161/slip44:60' -const ARBITRUM_USDC_ASSET_ID: AssetId = 'eip155:42161/erc20:0xaf88d065e77c8cc2239327c5edb3a432268e5831' +const ARBITRUM_USDC_ASSET_ID: AssetId = + 'eip155:42161/erc20:0xaf88d065e77c8cc2239327c5edb3a432268e5831' const BITCOIN_BTC_ASSET_ID: AssetId = 'bip122:000000000019d6689c085ae165831e93/slip44:0' const SOLANA_SOL_ASSET_ID: AssetId = 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/slip44:501' -const SOLANA_USDC_ASSET_ID: AssetId = 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/token:EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v' +const SOLANA_USDC_ASSET_ID: AssetId = + 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/token:EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v' export const CHAINFLIP_REGULAR_QUOTE = 'regular' export const CHAINFLIP_DCA_QUOTE = 'dca' @@ -34,7 +34,12 @@ export const ChainflipSupportedChainIds = [ export type ChainflipSupportedChainId = (typeof ChainflipSupportedChainIds)[number] export const ChainflipSupportedAssetIdsByChainId: Partial> = { - [KnownChainIds.EthereumMainnet]: [ETHEREUM_ETH_ASSET_ID, ETHEREUM_FLIP_ASSET_ID, ETHEREUM_USDC_ASSET_ID, ETHEREUM_USDT_ASSET_ID], + [KnownChainIds.EthereumMainnet]: [ + ETHEREUM_ETH_ASSET_ID, + ETHEREUM_FLIP_ASSET_ID, + ETHEREUM_USDC_ASSET_ID, + ETHEREUM_USDT_ASSET_ID, + ], [KnownChainIds.ArbitrumMainnet]: [ARBITRUM_ETH_ASSET_ID, ARBITRUM_USDC_ASSET_ID], [KnownChainIds.BitcoinMainnet]: [BITCOIN_BTC_ASSET_ID], [KnownChainIds.SolanaMainnet]: [SOLANA_SOL_ASSET_ID, SOLANA_USDC_ASSET_ID], @@ -49,12 +54,12 @@ export const chainIdToChainflipNetwork: Partial> = // TODO: Verify with chainflip if this are the correct values export const assetGasLimits: Partial> = { - ['eth.eth']: '34000', - ['flip.eth']: '52000', - ['usdc.eth']: '63000', - ['usdt.eth']: '70000', - ['eth.arb']: '100000', - ['usdc.arb']: '100000', + 'eth.eth': '34000', + 'flip.eth': '52000', + 'usdc.eth': '63000', + 'usdt.eth': '70000', + 'eth.arb': '100000', + 'usdc.arb': '100000', } export const CHAINFLIP_SUPPORTED_CHAIN_IDS: SupportedChainIds = { @@ -71,12 +76,12 @@ export const usdcAsset: Asset = { assetId: 'eip155:1/erc20:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', chainId: KnownChainIds.EthereumMainnet, color: '#2373CB', - explorer:'https://etherscan.io', - explorerAddressLink:'https://etherscan.io/address/', - explorerTxLink:'https://etherscan.io/tx/', - icon:'https://rawcdn.githack.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', - name:'USDC on Ethereum', + explorer: 'https://etherscan.io', + explorerAddressLink: 'https://etherscan.io/address/', + explorerTxLink: 'https://etherscan.io/tx/', + icon: 'https://rawcdn.githack.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + name: 'USDC on Ethereum', precision: 6, relatedAssetKey: 'eip155:1/erc20:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', - symbol:'USDC' + symbol: 'USDC', } diff --git a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/checkTradeStatus.ts b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/checkTradeStatus.ts index 3da368379d3..1a52aeed7f5 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/checkTradeStatus.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/checkTradeStatus.ts @@ -1,8 +1,10 @@ -import type { InterpolationOptions } from 'node-polyglot' import { TxStatus } from '@shapeshiftoss/unchained-client' +import type { InterpolationOptions } from 'node-polyglot' // @ts-ignore -export const checkTradeStatus = async (input): Promise<{ +export const checkTradeStatus = async ( + input, +): Promise<{ status: TxStatus buyTxHash: string | undefined message: string | [string, InterpolationOptions] | undefined @@ -13,4 +15,4 @@ export const checkTradeStatus = async (input): Promise<{ status: TxStatus.Unknown, message: undefined, } -} \ No newline at end of file +} diff --git a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts index 795dcd05686..d1452bcaa7a 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts @@ -1,39 +1,42 @@ +import type { AssetId } from '@shapeshiftoss/caip' +import { CHAIN_NAMESPACE, fromAssetId } from '@shapeshiftoss/caip' +import type { KnownChainIds } from '@shapeshiftoss/types' +import type { Result } from '@sniptt/monads' +import { Err, Ok } from '@sniptt/monads' +import type { AxiosError } from 'axios' import { v4 as uuid } from 'uuid' -import { AxiosError } from 'axios' -import { Err, Ok, Result } from '@sniptt/monads' -import { KnownChainIds } from '@shapeshiftoss/types' -import { AssetId, CHAIN_NAMESPACE, fromAssetId } from '@shapeshiftoss/caip' -import { - type GetEvmTradeQuoteInput, - GetTradeQuoteInput, +import { getDefaultSlippageDecimalPercentageForSwapper } from '../../../constants' +import type { + GetTradeQuoteInput, GetUtxoTradeQuoteInput, - type ProtocolFee, SwapErrorRight, SwapperDeps, - SwapperName, TradeQuote, - TradeQuoteError +} from '../../../types' +import { + type GetEvmTradeQuoteInput, + type ProtocolFee, + SwapperName, + TradeQuoteError, } from '../../../types' import { getRate, makeSwapErrorRight } from '../../../utils' -import { getDefaultSlippageDecimalPercentageForSwapper } from '../../../constants' - import { + CHAINFLIP_BAAS_COMMISSION, CHAINFLIP_BOOST_SWAP_SOURCE, CHAINFLIP_DCA_BOOST_SWAP_SOURCE, + CHAINFLIP_DCA_QUOTE, CHAINFLIP_DCA_SWAP_SOURCE, + CHAINFLIP_REGULAR_QUOTE, CHAINFLIP_SWAP_SOURCE, chainIdToChainflipNetwork, usdcAsset, - CHAINFLIP_BAAS_COMMISSION, - CHAINFLIP_REGULAR_QUOTE, - CHAINFLIP_DCA_QUOTE, } from '../constants' -import { ChainflipBaasQuoteQuote, ChainflipBaasQuoteQuoteFee } from '../models' -import { isSupportedAssetId, isSupportedChainId } from '../utils/helpers' +import type { ChainflipBaasQuoteQuote, ChainflipBaasQuoteQuoteFee } from '../models' import { chainflipService } from '../utils/chainflipService' import { getEvmTxFees } from '../utils/getEvmTxFees' import { getUtxoTxFees } from '../utils/getUtxoTxFees' +import { isSupportedAssetId, isSupportedChainId } from '../utils/helpers' export const getTradeQuote = async ( input: GetTradeQuoteInput, @@ -48,7 +51,7 @@ export const getTradeQuote = async ( affiliateBps: commissionBps, } = input - if (accountNumber == undefined) { + if (accountNumber === undefined) { return Err( makeSwapErrorRight({ message: `unsupported accountNumber`, @@ -56,7 +59,7 @@ export const getTradeQuote = async ( }), ) } - + if (!isSupportedChainId(sellAsset.chainId)) { return Err( makeSwapErrorRight({ @@ -97,39 +100,45 @@ export const getTradeQuote = async ( ) } - const sellChainflipChainKey = `${sellAsset.symbol.toLowerCase()}.${chainIdToChainflipNetwork[sellAsset.chainId as KnownChainIds]}` - const buyChainflipChainKey = `${buyAsset.symbol.toLowerCase()}.${chainIdToChainflipNetwork[buyAsset.chainId as KnownChainIds]}` + const sellChainflipChainKey = `${sellAsset.symbol.toLowerCase()}.${ + chainIdToChainflipNetwork[sellAsset.chainId as KnownChainIds] + }` + const buyChainflipChainKey = `${buyAsset.symbol.toLowerCase()}.${ + chainIdToChainflipNetwork[buyAsset.chainId as KnownChainIds] + }` const brokerUrl = deps.config.REACT_APP_CHAINFLIP_API_URL const apiKey = deps.config.REACT_APP_CHAINFLIP_API_KEY - + // Subtract the BaaS fee to end up at the final displayed commissionBps let serviceCommission = parseInt(commissionBps) - CHAINFLIP_BAAS_COMMISSION - if (serviceCommission < 0) - serviceCommission = 0 - + if (serviceCommission < 0) serviceCommission = 0 + const maybeQuoteResponse = await chainflipService.get( - `${brokerUrl}/quotes-native`+ - `?apiKey=${apiKey}` + - `&sourceAsset=${sellChainflipChainKey}` + - `&destinationAsset=${buyChainflipChainKey}` + - `&amount=${sellAmount}` + + `${brokerUrl}/quotes-native` + + `?apiKey=${apiKey}` + + `&sourceAsset=${sellChainflipChainKey}` + + `&destinationAsset=${buyChainflipChainKey}` + + `&amount=${sellAmount}` + `&commissionBps=${serviceCommission}`, ) if (maybeQuoteResponse.isErr()) { const error = maybeQuoteResponse.unwrapErr() const cause = error.cause as AxiosError - - if (cause.message.includes('code 400') && cause.response!.data.detail.includes('Amount outside asset bounds')) { - return Err( - makeSwapErrorRight({ - message: cause.response!.data.detail, - code: TradeQuoteError.SellAmountBelowMinimum, - }), - ) + + if ( + cause.message.includes('code 400') && + cause.response!.data.detail.includes('Amount outside asset bounds') + ) { + return Err( + makeSwapErrorRight({ + message: cause.response!.data.detail, + code: TradeQuoteError.SellAmountBelowMinimum, + }), + ) } - + return Err( makeSwapErrorRight({ message: 'Quote request failed', @@ -139,7 +148,7 @@ export const getTradeQuote = async ( } const { data: quoteResponse } = maybeQuoteResponse.unwrap() - + const getNetworkFeeCryptoBaseUnit = async () => { const { chainNamespace } = fromAssetId(sellAsset.assetId) @@ -149,7 +158,7 @@ export const getTradeQuote = async ( return await getEvmTxFees({ adapter: sellAdapter, supportsEIP1559: (input as GetEvmTradeQuoteInput).supportsEIP1559, - sendAsset: sellChainflipChainKey + sendAsset: sellChainflipChainKey, }) } @@ -162,76 +171,74 @@ export const getTradeQuote = async ( publicKey, }) } - + case CHAIN_NAMESPACE.Solana: { // TODO: Solana gas calc return undefined } } - + return undefined } - + const getFeeAsset = (fee: ChainflipBaasQuoteQuoteFee) => { - if (fee.type === 'ingress' || fee.type === 'boost') - return sellAsset + if (fee.type === 'ingress' || fee.type === 'boost') return sellAsset - if (fee.type === 'egress') - return buyAsset + if (fee.type === 'egress') return buyAsset - if (fee.type === 'liquidity' && fee.asset == sellChainflipChainKey) - return sellAsset + if (fee.type === 'liquidity' && fee.asset === sellChainflipChainKey) return sellAsset - if (fee.type === 'liquidity' && fee.asset == buyChainflipChainKey) - return buyAsset + if (fee.type === 'liquidity' && fee.asset === buyChainflipChainKey) return buyAsset - if (fee.type === 'liquidity' && fee.asset == "usdc.eth") - return usdcAsset + if (fee.type === 'liquidity' && fee.asset === 'usdc.eth') return usdcAsset - if (fee.type === "network") - return usdcAsset + if (fee.type === 'network') return usdcAsset } - + const getProtocolFees = (singleQuoteResponse: ChainflipBaasQuoteQuote) => { const protocolFees: Record = {} for (const fee of singleQuoteResponse.includedFees!) { - if (fee.type === "broker") - continue + if (fee.type === 'broker') continue const asset = getFeeAsset(fee)! if (!(asset.assetId in protocolFees)) { protocolFees[asset.assetId] = { - amountCryptoBaseUnit: "0", + amountCryptoBaseUnit: '0', requiresBalance: false, - asset: asset, + asset, } } - - protocolFees[asset.assetId].amountCryptoBaseUnit = - (BigInt(protocolFees[asset.assetId].amountCryptoBaseUnit) + BigInt(fee.amountNative!)).toString() + + protocolFees[asset.assetId].amountCryptoBaseUnit = ( + BigInt(protocolFees[asset.assetId].amountCryptoBaseUnit) + BigInt(fee.amountNative!) + ).toString() } return protocolFees } - + const getQuoteRate = (sellAmountCryptoBaseUnit: string, buyAmountCryptoBaseUnit: string) => { return getRate({ - sellAmountCryptoBaseUnit: sellAmountCryptoBaseUnit, - buyAmountCryptoBaseUnit: buyAmountCryptoBaseUnit, + sellAmountCryptoBaseUnit, + buyAmountCryptoBaseUnit, sellAsset, buyAsset, }) } - + const getSwapSource = (swapType: string | undefined, isBoosted: boolean) => { return swapType === CHAINFLIP_REGULAR_QUOTE - ? isBoosted ? CHAINFLIP_BOOST_SWAP_SOURCE : CHAINFLIP_SWAP_SOURCE - : isBoosted ? CHAINFLIP_DCA_BOOST_SWAP_SOURCE : CHAINFLIP_DCA_SWAP_SOURCE + ? isBoosted + ? CHAINFLIP_BOOST_SWAP_SOURCE + : CHAINFLIP_SWAP_SOURCE + : isBoosted + ? CHAINFLIP_DCA_BOOST_SWAP_SOURCE + : CHAINFLIP_DCA_SWAP_SOURCE } const quotes: TradeQuote[] = [] - + for (const singleQuoteResponse of quoteResponse) { const isStreaming = singleQuoteResponse.type === CHAINFLIP_DCA_QUOTE @@ -239,55 +246,63 @@ export const getTradeQuote = async ( // Streaming swaps are not enabled yet continue } - + if (singleQuoteResponse.boostQuote) { const boostRate = getQuoteRate( singleQuoteResponse.boostQuote.ingressAmountNative!, - singleQuoteResponse.boostQuote.egressAmountNative!) - + singleQuoteResponse.boostQuote.egressAmountNative!, + ) + const boostTradeQuote: TradeQuote = { id: uuid(), rate: boostRate, - receiveAddress: receiveAddress, + receiveAddress, potentialAffiliateBps: commissionBps, affiliateBps: commissionBps, - isStreaming: isStreaming, - slippageTolerancePercentageDecimal: getDefaultSlippageDecimalPercentageForSwapper(SwapperName.Chainflip), + isStreaming, + slippageTolerancePercentageDecimal: getDefaultSlippageDecimalPercentageForSwapper( + SwapperName.Chainflip, + ), steps: [ { buyAmountBeforeFeesCryptoBaseUnit: singleQuoteResponse.boostQuote.egressAmountNative!, buyAmountAfterFeesCryptoBaseUnit: singleQuoteResponse.boostQuote.egressAmountNative!, - sellAmountIncludingProtocolFeesCryptoBaseUnit: singleQuoteResponse.boostQuote.ingressAmountNative!, + sellAmountIncludingProtocolFeesCryptoBaseUnit: + singleQuoteResponse.boostQuote.ingressAmountNative!, feeData: { networkFeeCryptoBaseUnit: await getNetworkFeeCryptoBaseUnit(), protocolFees: getProtocolFees(singleQuoteResponse.boostQuote), }, rate: boostRate, source: getSwapSource(singleQuoteResponse.type, true), - buyAsset: buyAsset, - sellAsset: sellAsset, - accountNumber: accountNumber, - allowanceContract: "0x0", // Chainflip does not use contracts - estimatedExecutionTimeMs: singleQuoteResponse.boostQuote.estimatedDurationSeconds! * 1000 - } - ] + buyAsset, + sellAsset, + accountNumber, + allowanceContract: '0x0', // Chainflip does not use contracts + estimatedExecutionTimeMs: + singleQuoteResponse.boostQuote.estimatedDurationSeconds! * 1000, + }, + ], } quotes.push(boostTradeQuote) } - + const rate = getQuoteRate( singleQuoteResponse.ingressAmountNative!, - singleQuoteResponse.egressAmountNative!) - + singleQuoteResponse.egressAmountNative!, + ) + const tradeQuote: TradeQuote = { id: uuid(), - rate: rate, - receiveAddress: receiveAddress, + rate, + receiveAddress, potentialAffiliateBps: commissionBps, affiliateBps: commissionBps, - isStreaming: isStreaming, - slippageTolerancePercentageDecimal: getDefaultSlippageDecimalPercentageForSwapper(SwapperName.Chainflip), + isStreaming, + slippageTolerancePercentageDecimal: getDefaultSlippageDecimalPercentageForSwapper( + SwapperName.Chainflip, + ), steps: [ { buyAmountBeforeFeesCryptoBaseUnit: singleQuoteResponse.egressAmountNative!, @@ -297,17 +312,17 @@ export const getTradeQuote = async ( networkFeeCryptoBaseUnit: await getNetworkFeeCryptoBaseUnit(), protocolFees: getProtocolFees(singleQuoteResponse), }, - rate: rate, + rate, source: getSwapSource(singleQuoteResponse.type, false), - buyAsset: buyAsset, - sellAsset: sellAsset, - accountNumber: accountNumber, - allowanceContract: "0x0", // Chainflip does not use contracts - estimatedExecutionTimeMs: singleQuoteResponse.estimatedDurationSeconds! * 1000 - } - ] + buyAsset, + sellAsset, + accountNumber, + allowanceContract: '0x0', // Chainflip does not use contracts + estimatedExecutionTimeMs: singleQuoteResponse.estimatedDurationSeconds! * 1000, + }, + ], } - + quotes.push(tradeQuote) } diff --git a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts index ca17b70e3cd..9f84d03d00b 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts @@ -1,19 +1,12 @@ -import { AxiosError } from 'axios' import { fromAssetId, fromChainId } from '@shapeshiftoss/caip' -import { KnownChainIds } from '@shapeshiftoss/types' import { getErc20Data, getFees } from '@shapeshiftoss/chain-adapters/dist/evm/utils' +import type { KnownChainIds } from '@shapeshiftoss/types' +import type { AxiosError } from 'axios' -import type { - EvmTransactionRequest, - GetUnsignedEvmTransactionArgs -} from '../../../types' +import type { EvmTransactionRequest, GetUnsignedEvmTransactionArgs } from '../../../types' import { isExecutableTradeQuote } from '../../../utils' - -import { - chainIdToChainflipNetwork, - CHAINFLIP_BAAS_COMMISSION -} from '../constants' -import { ChainflipBaasSwapDepositAddress } from '../models' +import { CHAINFLIP_BAAS_COMMISSION, chainIdToChainflipNetwork } from '../constants' +import type { ChainflipBaasSwapDepositAddress } from '../models' import { chainflipService } from '../utils/chainflipService' import { getGasLimit } from '../utils/helpers' @@ -23,7 +16,7 @@ export const getUnsignedEvmTransaction = async ({ tradeQuote, supportsEIP1559, assertGetEvmChainAdapter, - config + config, }: GetUnsignedEvmTransactionArgs): Promise => { if (!isExecutableTradeQuote(tradeQuote)) throw Error('Unable to execute trade') @@ -31,17 +24,20 @@ export const getUnsignedEvmTransaction = async ({ const apiKey = config.REACT_APP_CHAINFLIP_API_KEY const step = tradeQuote.steps[0] - const sellChainflipChainKey = `${step.sellAsset.symbol.toLowerCase()}.${chainIdToChainflipNetwork[step.sellAsset.chainId as KnownChainIds]}` - const buyChainflipChainKey = `${step.buyAsset.symbol.toLowerCase()}.${chainIdToChainflipNetwork[step.buyAsset.chainId as KnownChainIds]}` - + const sellChainflipChainKey = `${step.sellAsset.symbol.toLowerCase()}.${ + chainIdToChainflipNetwork[step.sellAsset.chainId as KnownChainIds] + }` + const buyChainflipChainKey = `${step.buyAsset.symbol.toLowerCase()}.${ + chainIdToChainflipNetwork[step.buyAsset.chainId as KnownChainIds] + }` + // Subtract the BaaS fee to end up at the final displayed commissionBps let serviceCommission = parseInt(tradeQuote.affiliateBps) - CHAINFLIP_BAAS_COMMISSION - if (serviceCommission < 0) - serviceCommission = 0 - + if (serviceCommission < 0) serviceCommission = 0 + const maybeSwapResponse = await chainflipService.get( - `${brokerUrl}/swap` + - `?apiKey=${apiKey}` + + `${brokerUrl}/swap` + + `?apiKey=${apiKey}` + `&sourceAsset=${sellChainflipChainKey}` + `&destinationAsset=${buyChainflipChainKey}` + `&destinationAddress=${tradeQuote.receiveAddress}` + @@ -51,43 +47,50 @@ export const getUnsignedEvmTransaction = async ({ // `&refundAddress=${from}` + // `&retryDurationInBlocks=10` + `&commissionBps=${serviceCommission}`, - + // TODO: Below is the reference code of Chainflip to calculate the minPrice parameter // const tolerance = new BigNumber(params.slippageTolerancePercent); // const estimatedPrice = new BigNumber(quote.estimatedPrice); // minPrice = estimatedPrice // .times(new BigNumber(100).minus(tolerance).dividedBy(100)) // .toFixed(assetConstants[destAsset].decimals); - + // TODO: For DCA swaps we need to add the numberOfChunks/chunkIntervalBlocks parameters ) - + if (maybeSwapResponse.isErr()) { const error = maybeSwapResponse.unwrapErr() const cause = error.cause as AxiosError - throw Error(cause.response!.data.detail); + throw Error(cause.response!.data.detail) } const { data: swapResponse } = maybeSwapResponse.unwrap() - + const depositAddress = swapResponse.address! const { assetReference } = fromAssetId(step.sellAsset.assetId) const isTokenSend = !!assetReference - + const adapter = assertGetEvmChainAdapter(chainId) const fees = await getFees({ - adapter: adapter, + adapter, to: depositAddress, - from: from, - value: (isTokenSend ? 0n : BigInt(step.sellAmountIncludingProtocolFeesCryptoBaseUnit)).toString(), - data: (await getErc20Data(depositAddress, step.sellAmountIncludingProtocolFeesCryptoBaseUnit, assetReference)), - supportsEIP1559: supportsEIP1559 + from, + value: (isTokenSend + ? 0n + : BigInt(step.sellAmountIncludingProtocolFeesCryptoBaseUnit) + ).toString(), + data: await getErc20Data( + depositAddress, + step.sellAmountIncludingProtocolFeesCryptoBaseUnit, + assetReference, + ), + supportsEIP1559, }) const tx = await adapter.buildSendApiTransaction({ to: depositAddress, - from: from, + from, value: step.sellAmountIncludingProtocolFeesCryptoBaseUnit, accountNumber: step.accountNumber, chainSpecific: { @@ -95,18 +98,18 @@ export const getUnsignedEvmTransaction = async ({ contractAddress: assetReference, maxFeePerGas: fees.maxFeePerGas!, maxPriorityFeePerGas: fees.maxPriorityFeePerGas!, - } + }, }) - + return { chainId: Number(fromChainId(chainId).chainReference), data: tx.data, to: tx.to, - from: from, + from, value: tx.value, gasLimit: tx.gasLimit, maxFeePerGas: tx.maxFeePerGas, maxPriorityFeePerGas: tx.maxPriorityFeePerGas, - gasPrice: tx.gasPrice + gasPrice: tx.gasPrice, } -} \ No newline at end of file +} diff --git a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedUtxoTransaction.ts b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedUtxoTransaction.ts index cfa2b9e5937..d32b5b72510 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedUtxoTransaction.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedUtxoTransaction.ts @@ -1,19 +1,12 @@ -import { AxiosError } from 'axios'; import type { BTCSignTx } from '@shapeshiftoss/hdwallet-core' -import { KnownChainIds } from '@shapeshiftoss/types'; +import type { KnownChainIds } from '@shapeshiftoss/types' +import type { AxiosError } from 'axios' -import { - CHAINFLIP_BAAS_COMMISSION, - chainIdToChainflipNetwork -} from '../constants'; -import { chainflipService } from '../utils/chainflipService'; -import { ChainflipBaasSwapDepositAddress } from '../models'; - -import type { - GetUnsignedUtxoTransactionArgs, - UtxoFeeData -} from '../../../types' +import type { GetUnsignedUtxoTransactionArgs, UtxoFeeData } from '../../../types' import { isExecutableTradeQuote } from '../../../utils' +import { CHAINFLIP_BAAS_COMMISSION, chainIdToChainflipNetwork } from '../constants' +import type { ChainflipBaasSwapDepositAddress } from '../models' +import { chainflipService } from '../utils/chainflipService' export const getUnsignedUtxoTransaction = async ({ tradeQuote, @@ -26,28 +19,31 @@ export const getUnsignedUtxoTransaction = async ({ const brokerUrl = config.REACT_APP_CHAINFLIP_API_URL const apiKey = config.REACT_APP_CHAINFLIP_API_KEY - + const step = tradeQuote.steps[0] - const sellChainflipChainKey = `${step.sellAsset.symbol.toLowerCase()}.${chainIdToChainflipNetwork[step.sellAsset.chainId as KnownChainIds]}` - const buyChainflipChainKey = `${step.buyAsset.symbol.toLowerCase()}.${chainIdToChainflipNetwork[step.buyAsset.chainId as KnownChainIds]}` + const sellChainflipChainKey = `${step.sellAsset.symbol.toLowerCase()}.${ + chainIdToChainflipNetwork[step.sellAsset.chainId as KnownChainIds] + }` + const buyChainflipChainKey = `${step.buyAsset.symbol.toLowerCase()}.${ + chainIdToChainflipNetwork[step.buyAsset.chainId as KnownChainIds] + }` // Subtract the BaaS fee to end up at the final displayed commissionBps let serviceCommission = parseInt(tradeQuote.affiliateBps) - CHAINFLIP_BAAS_COMMISSION - if (serviceCommission < 0) - serviceCommission = 0 + if (serviceCommission < 0) serviceCommission = 0 const maybeSwapResponse = await chainflipService.get( `${brokerUrl}/swap` + - `?apiKey=${apiKey}` + - `&sourceAsset=${sellChainflipChainKey}` + - `&destinationAsset=${buyChainflipChainKey}` + - `&destinationAddress=${tradeQuote.receiveAddress}` + - `&boostFee=10` + - // TODO: Calculate minprice based on tradeQuote.slippageTolerancePercentageDecimal, step.sellAmountIncludingProtocolFeesCryptoBaseUnit - // `&minimumPrice=` + - // `&refundAddress=${from}` + - // `&retryDurationInBlocks=10` + - `&commissionBps=${serviceCommission}`, + `?apiKey=${apiKey}` + + `&sourceAsset=${sellChainflipChainKey}` + + `&destinationAsset=${buyChainflipChainKey}` + + `&destinationAddress=${tradeQuote.receiveAddress}` + + `&boostFee=10` + + // TODO: Calculate minprice based on tradeQuote.slippageTolerancePercentageDecimal, step.sellAmountIncludingProtocolFeesCryptoBaseUnit + // `&minimumPrice=` + + // `&refundAddress=${from}` + + // `&retryDurationInBlocks=10` + + `&commissionBps=${serviceCommission}`, // TODO: For DCA swaps we need to add the numberOfChunks/chunkIntervalBlocks parameters ) @@ -55,13 +51,13 @@ export const getUnsignedUtxoTransaction = async ({ if (maybeSwapResponse.isErr()) { const error = maybeSwapResponse.unwrapErr() const cause = error.cause as AxiosError - throw Error(cause.response!.data.detail); + throw Error(cause.response!.data.detail) } const { data: swapResponse } = maybeSwapResponse.unwrap() - + const depositAddress = swapResponse.address! - + return assertGetUtxoChainAdapter(step.sellAsset.chainId).buildSendApiTransaction({ value: step.sellAmountIncludingProtocolFeesCryptoBaseUnit, xpub: xpub!, diff --git a/packages/swapper/src/swappers/ChainflipSwapper/utils/chainflipService.ts b/packages/swapper/src/swappers/ChainflipSwapper/utils/chainflipService.ts index 365adf87f0a..5b087a231c7 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/utils/chainflipService.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/utils/chainflipService.ts @@ -2,18 +2,19 @@ import { SwapperName } from '../../../types' import { createCache, makeSwapperAxiosServiceMonadic } from '../../../utils' const maxAge = 60 * 60 * 1000 // 1 hour cache for assets -const cachedUrls = [ - '/assets/', -] +const cachedUrls = ['/assets/'] const axiosConfig = { - timeout: 10000, - headers: { - Accept: 'application/json', - 'Content-Type': 'application/json', - }, + timeout: 10000, + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + }, } const chainflipServiceBase = createCache(maxAge, cachedUrls, axiosConfig) -export const chainflipService = makeSwapperAxiosServiceMonadic(chainflipServiceBase, SwapperName.Chainflip) +export const chainflipService = makeSwapperAxiosServiceMonadic( + chainflipServiceBase, + SwapperName.Chainflip, +) diff --git a/packages/swapper/src/swappers/ChainflipSwapper/utils/getEvmTxFees.ts b/packages/swapper/src/swappers/ChainflipSwapper/utils/getEvmTxFees.ts index 38dd9bf99ed..0e1768bdf77 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/utils/getEvmTxFees.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/utils/getEvmTxFees.ts @@ -5,7 +5,7 @@ import { getGasLimit } from './helpers' type GetEvmTxFeesArgs = { adapter: EvmChainAdapter - supportsEIP1559: boolean, + supportsEIP1559: boolean sendAsset: string } @@ -15,10 +15,10 @@ export const getEvmTxFees = async (args: GetEvmTxFeesArgs): Promise => { const { average } = await adapter.getGasFeeData() const gasLimit = getGasLimit(args.sendAsset) - + return evm.calcNetworkFeeCryptoBaseUnit({ ...average, supportsEIP1559, - gasLimit + gasLimit, }) } diff --git a/packages/swapper/src/swappers/ChainflipSwapper/utils/getUtxoTxFees.ts b/packages/swapper/src/swappers/ChainflipSwapper/utils/getUtxoTxFees.ts index f97cb30581e..a89fafb66e0 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/utils/getUtxoTxFees.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/utils/getUtxoTxFees.ts @@ -1,17 +1,17 @@ -import type {GetFeeDataInput, UtxoChainAdapter} from '@shapeshiftoss/chain-adapters' +import type { GetFeeDataInput, UtxoChainAdapter } from '@shapeshiftoss/chain-adapters' import type { UtxoChainId } from '@shapeshiftoss/types' import { bn } from '@shapeshiftoss/utils' type GetUtxoTxFeesInput = { sellAmountCryptoBaseUnit: string - sellAdapter: UtxoChainAdapter, + sellAdapter: UtxoChainAdapter publicKey: string } export const getUtxoTxFees = async ({ sellAmountCryptoBaseUnit, sellAdapter, - publicKey + publicKey, }: GetUtxoTxFeesInput): Promise => { // TODO: Get Chainflip BTC vault address const getFeeDataInput: GetFeeDataInput = { @@ -19,10 +19,10 @@ export const getUtxoTxFees = async ({ value: sellAmountCryptoBaseUnit, chainSpecific: { pubkey: publicKey }, } - + const feeDataOptions = await sellAdapter.getFeeData(getFeeDataInput) const feeData = feeDataOptions['fast'] - + return bn(feeData.txFee).dp(0).toString() } diff --git a/packages/swapper/src/swappers/ChainflipSwapper/utils/helpers.ts b/packages/swapper/src/swappers/ChainflipSwapper/utils/helpers.ts index 7af24df577f..53b6b05c8de 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/utils/helpers.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/utils/helpers.ts @@ -1,26 +1,40 @@ import { - type ChainId, + arbitrumAssetId, type AssetId, - fromAssetId, - ethAssetId, avalancheAssetId, - optimismAssetId, bscAssetId, polygonAssetId, gnosisAssetId, arbitrumAssetId, baseAssetId + baseAssetId, + bscAssetId, + type ChainId, + ethAssetId, + fromAssetId, + gnosisAssetId, + optimismAssetId, + polygonAssetId, } from '@shapeshiftoss/caip' -import { KnownChainIds } from "@shapeshiftoss/types"; +import { KnownChainIds } from '@shapeshiftoss/types' -import { assetGasLimits, ChainflipSupportedChainId } from '../constants' -import { ChainflipSupportedChainIds, ChainflipSupportedAssetIdsByChainId } from '../constants' +import type { ChainflipSupportedChainId } from '../constants' +import { + assetGasLimits, + ChainflipSupportedAssetIdsByChainId, + ChainflipSupportedChainIds, +} from '../constants' export const isSupportedChainId = (chainId: ChainId): chainId is ChainflipSupportedChainId => { return ChainflipSupportedChainIds.includes(chainId as ChainflipSupportedChainId) } -export const isSupportedAssetId = (chainId: ChainId, assetId: AssetId): chainId is ChainflipSupportedChainId => { - return ChainflipSupportedAssetIdsByChainId[chainId as ChainflipSupportedChainId]!.includes(assetId) +export const isSupportedAssetId = ( + chainId: ChainId, + assetId: AssetId, +): chainId is ChainflipSupportedChainId => { + return ChainflipSupportedAssetIdsByChainId[chainId as ChainflipSupportedChainId]!.includes( + assetId, + ) } export const getGasLimit = (chainflipAsset: string) => { - return (chainflipAsset in assetGasLimits) ? assetGasLimits[chainflipAsset]! : '100000' + return chainflipAsset in assetGasLimits ? assetGasLimits[chainflipAsset]! : '100000' } export const isNativeEvmAsset = (assetId: AssetId): boolean => { @@ -45,4 +59,4 @@ export const isNativeEvmAsset = (assetId: AssetId): boolean => { default: return false } -} \ No newline at end of file +} diff --git a/packages/swapper/src/types.ts b/packages/swapper/src/types.ts index 2f6b8b6c208..46561bf8d16 100644 --- a/packages/swapper/src/types.ts +++ b/packages/swapper/src/types.ts @@ -46,8 +46,8 @@ export type SwapperConfig = { REACT_APP_COWSWAP_BASE_URL: string REACT_APP_PORTALS_BASE_URL: string REACT_APP_FEATURE_ZRX_PERMIT2: boolean - REACT_APP_ZRX_BASE_URL: string, - REACT_APP_FEATURE_CHAINFLIP_DCA: boolean, + REACT_APP_ZRX_BASE_URL: string + REACT_APP_FEATURE_CHAINFLIP_DCA: boolean REACT_APP_CHAINFLIP_API_KEY: string REACT_APP_CHAINFLIP_API_URL: string } diff --git a/react-app-rewired/headers/csps/chainflip.ts b/react-app-rewired/headers/csps/chainflip.ts index 8030940e5f4..776467dc639 100644 --- a/react-app-rewired/headers/csps/chainflip.ts +++ b/react-app-rewired/headers/csps/chainflip.ts @@ -1,7 +1,5 @@ import type { Csp } from '../types' export const csp: Csp = { - 'connect-src': [ - 'https://chainflip-broker.io/', - ], + 'connect-src': ['https://chainflip-broker.io/'], } diff --git a/src/components/MultiHopTrade/components/TradeInput/components/SwapperIcon/SwapperIcon.tsx b/src/components/MultiHopTrade/components/TradeInput/components/SwapperIcon/SwapperIcon.tsx index b9e918fe9e9..92dce1188fb 100644 --- a/src/components/MultiHopTrade/components/TradeInput/components/SwapperIcon/SwapperIcon.tsx +++ b/src/components/MultiHopTrade/components/TradeInput/components/SwapperIcon/SwapperIcon.tsx @@ -4,13 +4,13 @@ import { useMemo } from 'react' import { LazyLoadAvatar } from 'components/LazyLoadAvatar' import { assertUnreachable } from 'lib/utils' +import ZrxIcon from './0x-icon.png' import ArbitrumBridgeIcon from './arbitrum-bridge-icon.png' import ChainflipIcon from './chainflip-icon.png' import CowIcon from './cow-icon.png' import LiFiIcon from './lifi-icon.png' import PortalsIcon from './portals-icon.png' import THORChainIcon from './thorchain-icon.png' -import ZrxIcon from './0x-icon.png' export const SwapperIcon = ({ swapperName, diff --git a/src/state/helpers.ts b/src/state/helpers.ts index 2e5f6b01c4e..2a77bb7a9f8 100644 --- a/src/state/helpers.ts +++ b/src/state/helpers.ts @@ -5,14 +5,14 @@ import type { FeatureFlags } from './slices/preferencesSlice/preferencesSlice' export const isCrossAccountTradeSupported = (swapperName: SwapperName) => { switch (swapperName) { - case SwapperName.Chainflip: - case SwapperName.LIFI: case SwapperName.Thorchain: + case SwapperName.LIFI: + case SwapperName.Chainflip: return true - case SwapperName.ArbitrumBridge: + case SwapperName.Zrx: case SwapperName.CowSwap: + case SwapperName.ArbitrumBridge: case SwapperName.Portals: - case SwapperName.Zrx: case SwapperName.Test: // Technically supported for Arbitrum Bridge, but we disable it for the sake of simplicity for now return false @@ -22,25 +22,25 @@ export const isCrossAccountTradeSupported = (swapperName: SwapperName) => { } export const getEnabledSwappers = ( - { ArbitrumBridge, Chainflip, Cowswap, LifiSwap, Portals, ThorSwap, ZrxSwap }: FeatureFlags, + { Chainflip, Portals, LifiSwap, ThorSwap, ZrxSwap, ArbitrumBridge, Cowswap }: FeatureFlags, isCrossAccountTrade: boolean, ): Record => { return { - [SwapperName.ArbitrumBridge]: - ArbitrumBridge && - (!isCrossAccountTrade || isCrossAccountTradeSupported(SwapperName.ArbitrumBridge)), - [SwapperName.Chainflip]: - Chainflip && (!isCrossAccountTrade || isCrossAccountTradeSupported(SwapperName.Chainflip)), - [SwapperName.CowSwap]: - Cowswap && (!isCrossAccountTrade || isCrossAccountTradeSupported(SwapperName.CowSwap)), [SwapperName.LIFI]: LifiSwap && (!isCrossAccountTrade || isCrossAccountTradeSupported(SwapperName.LIFI)), - [SwapperName.Portals]: - Portals && (!isCrossAccountTrade || isCrossAccountTradeSupported(SwapperName.Portals)), [SwapperName.Thorchain]: ThorSwap && (!isCrossAccountTrade || isCrossAccountTradeSupported(SwapperName.Thorchain)), [SwapperName.Zrx]: ZrxSwap && (!isCrossAccountTrade || isCrossAccountTradeSupported(SwapperName.Zrx)), + [SwapperName.CowSwap]: + Cowswap && (!isCrossAccountTrade || isCrossAccountTradeSupported(SwapperName.CowSwap)), + [SwapperName.ArbitrumBridge]: + ArbitrumBridge && + (!isCrossAccountTrade || isCrossAccountTradeSupported(SwapperName.ArbitrumBridge)), + [SwapperName.Portals]: + Portals && (!isCrossAccountTrade || isCrossAccountTradeSupported(SwapperName.Portals)), + [SwapperName.Chainflip]: + Chainflip && (!isCrossAccountTrade || isCrossAccountTradeSupported(SwapperName.Chainflip)), [SwapperName.Test]: false, } } From 1fd442bbad67270053e34ff44fcfd21a766dba96 Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Thu, 31 Oct 2024 08:45:31 +0900 Subject: [PATCH 061/127] feat: improve types --- .../swapperApi/checkTradeStatus.ts | 2 +- .../ChainflipSwapper/utils/helpers.ts | 39 +------------------ packages/swapper/src/types.ts | 12 +++--- .../components/SwapperIcon/SwapperIcon.tsx | 20 +++++----- .../useGetTradeQuotes/useGetTradeQuotes.tsx | 6 +-- 5 files changed, 21 insertions(+), 58 deletions(-) diff --git a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/checkTradeStatus.ts b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/checkTradeStatus.ts index 1a52aeed7f5..53c4893f1ef 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/checkTradeStatus.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/checkTradeStatus.ts @@ -1,8 +1,8 @@ import { TxStatus } from '@shapeshiftoss/unchained-client' import type { InterpolationOptions } from 'node-polyglot' -// @ts-ignore export const checkTradeStatus = async ( + // @ts-ignore unimplemented yet input, ): Promise<{ status: TxStatus diff --git a/packages/swapper/src/swappers/ChainflipSwapper/utils/helpers.ts b/packages/swapper/src/swappers/ChainflipSwapper/utils/helpers.ts index 53b6b05c8de..86543cfcb79 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/utils/helpers.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/utils/helpers.ts @@ -1,17 +1,4 @@ -import { - arbitrumAssetId, - type AssetId, - avalancheAssetId, - baseAssetId, - bscAssetId, - type ChainId, - ethAssetId, - fromAssetId, - gnosisAssetId, - optimismAssetId, - polygonAssetId, -} from '@shapeshiftoss/caip' -import { KnownChainIds } from '@shapeshiftoss/types' +import { type AssetId, type ChainId } from '@shapeshiftoss/caip' import type { ChainflipSupportedChainId } from '../constants' import { @@ -36,27 +23,3 @@ export const isSupportedAssetId = ( export const getGasLimit = (chainflipAsset: string) => { return chainflipAsset in assetGasLimits ? assetGasLimits[chainflipAsset]! : '100000' } - -export const isNativeEvmAsset = (assetId: AssetId): boolean => { - const { chainId } = fromAssetId(assetId) - switch (chainId) { - case KnownChainIds.EthereumMainnet: - return assetId === ethAssetId - case KnownChainIds.AvalancheMainnet: - return assetId === avalancheAssetId - case KnownChainIds.OptimismMainnet: - return assetId === optimismAssetId - case KnownChainIds.BnbSmartChainMainnet: - return assetId === bscAssetId - case KnownChainIds.PolygonMainnet: - return assetId === polygonAssetId - case KnownChainIds.GnosisMainnet: - return assetId === gnosisAssetId - case KnownChainIds.ArbitrumMainnet: - return assetId === arbitrumAssetId - case KnownChainIds.BaseMainnet: - return assetId === baseAssetId - default: - return false - } -} diff --git a/packages/swapper/src/types.ts b/packages/swapper/src/types.ts index 46561bf8d16..efebb80d7cf 100644 --- a/packages/swapper/src/types.ts +++ b/packages/swapper/src/types.ts @@ -47,20 +47,20 @@ export type SwapperConfig = { REACT_APP_PORTALS_BASE_URL: string REACT_APP_FEATURE_ZRX_PERMIT2: boolean REACT_APP_ZRX_BASE_URL: string - REACT_APP_FEATURE_CHAINFLIP_DCA: boolean REACT_APP_CHAINFLIP_API_KEY: string REACT_APP_CHAINFLIP_API_URL: string + REACT_APP_FEATURE_CHAINFLIP_DCA: boolean } export enum SwapperName { - ArbitrumBridge = 'Arbitrum Bridge', - Chainflip = 'Chainflip', - CowSwap = 'CoW Swap', - LIFI = 'LI.FI', - Portals = 'Portals', Thorchain = 'THORChain', + CowSwap = 'CoW Swap', Zrx = '0x', Test = 'Test', + LIFI = 'LI.FI', + ArbitrumBridge = 'Arbitrum Bridge', + Portals = 'Portals', + Chainflip = 'Chainflip', } export type SwapSource = SwapperName | `${SwapperName} • ${string}` diff --git a/src/components/MultiHopTrade/components/TradeInput/components/SwapperIcon/SwapperIcon.tsx b/src/components/MultiHopTrade/components/TradeInput/components/SwapperIcon/SwapperIcon.tsx index 92dce1188fb..a9a1a24e72b 100644 --- a/src/components/MultiHopTrade/components/TradeInput/components/SwapperIcon/SwapperIcon.tsx +++ b/src/components/MultiHopTrade/components/TradeInput/components/SwapperIcon/SwapperIcon.tsx @@ -21,20 +21,20 @@ export const SwapperIcon = ({ }) => { const icon = useMemo(() => { switch (swapperName) { - case SwapperName.ArbitrumBridge: - return ArbitrumBridgeIcon - case SwapperName.Chainflip: - return ChainflipIcon - case SwapperName.CowSwap: - return CowIcon case SwapperName.LIFI: return LiFiIcon - case SwapperName.Portals: - return PortalsIcon - case SwapperName.Thorchain: - return THORChainIcon + case SwapperName.CowSwap: + return CowIcon case SwapperName.Zrx: return ZrxIcon + case SwapperName.Thorchain: + return THORChainIcon + case SwapperName.ArbitrumBridge: + return ArbitrumBridgeIcon + case SwapperName.Portals: + return PortalsIcon + case SwapperName.Chainflip: + return ChainflipIcon case SwapperName.Test: return '' default: diff --git a/src/components/MultiHopTrade/hooks/useGetTradeQuotes/useGetTradeQuotes.tsx b/src/components/MultiHopTrade/hooks/useGetTradeQuotes/useGetTradeQuotes.tsx index c8ae2a61d39..d4231c8d7b8 100644 --- a/src/components/MultiHopTrade/hooks/useGetTradeQuotes/useGetTradeQuotes.tsx +++ b/src/components/MultiHopTrade/hooks/useGetTradeQuotes/useGetTradeQuotes.tsx @@ -289,13 +289,13 @@ export const useGetTradeQuotes = () => { [shouldRefetchTradeQuotes, tradeQuoteInput], ) - useGetSwapperTradeQuote(getTradeQuoteArgs(SwapperName.ArbitrumBridge)) - useGetSwapperTradeQuote(getTradeQuoteArgs(SwapperName.Chainflip)) useGetSwapperTradeQuote(getTradeQuoteArgs(SwapperName.CowSwap)) - useGetSwapperTradeQuote(getTradeQuoteArgs(SwapperName.LIFI)) + useGetSwapperTradeQuote(getTradeQuoteArgs(SwapperName.ArbitrumBridge)) useGetSwapperTradeQuote(getTradeQuoteArgs(SwapperName.Portals)) + useGetSwapperTradeQuote(getTradeQuoteArgs(SwapperName.LIFI)) useGetSwapperTradeQuote(getTradeQuoteArgs(SwapperName.Thorchain)) useGetSwapperTradeQuote(getTradeQuoteArgs(SwapperName.Zrx)) + useGetSwapperTradeQuote(getTradeQuoteArgs(SwapperName.Chainflip)) // true if any debounce, input or swapper is fetching const isAnyTradeQuoteLoading = useAppSelector(selectIsAnyTradeQuoteLoading) From dccd703698abaf03f597fca7e7ae4f289506f737 Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Thu, 31 Oct 2024 08:47:56 +0900 Subject: [PATCH 062/127] feat: cleanup unused models --- .../models/ChainflipBaasQuoteBoostQuote.ts | 168 ------------ .../models/ChainflipBaasQuotePoolFee.ts | 82 ------ .../models/ChainflipBaasQuotePoolInfo.ts | 89 ------- .../ChainflipBaasStatusAffiliateBroker.ts | 72 ------ .../models/ChainflipBaasStatusBoost.ts | 114 -------- .../ChainflipBaasStatusCcmParameters.ts | 79 ------ .../models/ChainflipBaasStatusChunkInfo.ts | 149 ----------- .../models/ChainflipBaasStatusDca.ts | 95 ------- .../ChainflipBaasStatusDcaParameters.ts | 72 ------ .../models/ChainflipBaasStatusDeposit.ts | 143 ----------- .../ChainflipBaasStatusDepositChannel.ts | 184 ------------- .../models/ChainflipBaasStatusEgress.ts | 150 ----------- .../models/ChainflipBaasStatusFailure.ts | 101 -------- ...ChainflipBaasStatusFillOrKillParameters.ts | 79 ------ .../models/ChainflipBaasStatusPaidFee.ts | 101 -------- .../models/ChainflipBaasStatusReason.ts | 72 ------ .../ChainflipBaasStatusStatusResponse.ts | 81 ------ .../models/ChainflipBaasStatusSwap.ts | 167 ------------ .../models/ChainflipBaasStatusSwapStatus.ts | 243 ------------------ 19 files changed, 2241 deletions(-) delete mode 100644 packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasQuoteBoostQuote.ts delete mode 100644 packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasQuotePoolFee.ts delete mode 100644 packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasQuotePoolInfo.ts delete mode 100644 packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusAffiliateBroker.ts delete mode 100644 packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusBoost.ts delete mode 100644 packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusCcmParameters.ts delete mode 100644 packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusChunkInfo.ts delete mode 100644 packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusDca.ts delete mode 100644 packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusDcaParameters.ts delete mode 100644 packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusDeposit.ts delete mode 100644 packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusDepositChannel.ts delete mode 100644 packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusEgress.ts delete mode 100644 packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusFailure.ts delete mode 100644 packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusFillOrKillParameters.ts delete mode 100644 packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusPaidFee.ts delete mode 100644 packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusReason.ts delete mode 100644 packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusStatusResponse.ts delete mode 100644 packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusSwap.ts delete mode 100644 packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusSwapStatus.ts diff --git a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasQuoteBoostQuote.ts b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasQuoteBoostQuote.ts deleted file mode 100644 index 268ac2ea76b..00000000000 --- a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasQuoteBoostQuote.ts +++ /dev/null @@ -1,168 +0,0 @@ -// @ts-nocheck -/* tslint:disable */ -/* eslint-disable */ -/** - * Chainflip Broker as a Service - * Run your own Chainflip Broker without any hassle. - * - * The version of the OpenAPI document: v1 - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - -import { exists, mapValues } from '../runtime'; -import type { ChainflipBaasQuotePoolInfo } from './ChainflipBaasQuotePoolInfo'; -import { - ChainflipBaasQuotePoolInfoFromJSON, - ChainflipBaasQuotePoolInfoFromJSONTyped, - ChainflipBaasQuotePoolInfoToJSON, -} from './ChainflipBaasQuotePoolInfo'; -import type { ChainflipBaasQuoteQuoteFee } from './ChainflipBaasQuoteQuoteFee'; -import { - ChainflipBaasQuoteQuoteFeeFromJSON, - ChainflipBaasQuoteQuoteFeeFromJSONTyped, - ChainflipBaasQuoteQuoteFeeToJSON, -} from './ChainflipBaasQuoteQuoteFee'; - -/** - * An optional quote to have the swap boosted. - * @export - * @interface ChainflipBaasQuoteBoostQuote - */ -export interface ChainflipBaasQuoteBoostQuote { - /** - * The asset to send. - * @type {string} - * @memberof ChainflipBaasQuoteBoostQuote - */ - ingressAsset?: string; - /** - * The amount to send. - * @type {number} - * @memberof ChainflipBaasQuoteBoostQuote - */ - ingressAmount?: number; - /** - * The amount to send in native units. - * @type {string} - * @memberof ChainflipBaasQuoteBoostQuote - */ - readonly ingressAmountNative?: string; - /** - * The asset to receive. - * @type {string} - * @memberof ChainflipBaasQuoteBoostQuote - */ - egressAsset?: string; - /** - * The amount to receive. - * @type {number} - * @memberof ChainflipBaasQuoteBoostQuote - */ - readonly egressAmount?: number; - /** - * The amount to receive in native units. - * @type {string} - * @memberof ChainflipBaasQuoteBoostQuote - */ - readonly egressAmountNative?: string; - /** - * The fee structure, this includes all fees. - * @type {Array} - * @memberof ChainflipBaasQuoteBoostQuote - */ - readonly includedFees?: Array; - /** - * A warning in case liquidity is low and there is a risk of high slippage. - * @type {boolean} - * @memberof ChainflipBaasQuoteBoostQuote - */ - readonly lowLiquidityWarning?: boolean; - /** - * Liquidity pools involved in the swap, as well as estimated liquidity provider fees. - * @type {Array} - * @memberof ChainflipBaasQuoteBoostQuote - */ - poolInfo?: Array; - /** - * The estimated time the swap will take. - * @type {number} - * @memberof ChainflipBaasQuoteBoostQuote - */ - readonly estimatedDurationSeconds?: number; - /** - * The estimated fee (in bps) that the user has to pay (from the deposit amount) to get this swap boosted. - * @type {number} - * @memberof ChainflipBaasQuoteBoostQuote - */ - readonly estimatedBoostFeeBps?: number; - /** - * The number of "sub-swaps" to perform for a DCA swap. - * @type {number} - * @memberof ChainflipBaasQuoteBoostQuote - */ - chunkIntervalBlocks?: number | null; - /** - * The delay between the "sub-swaps" of a DCA swap in number of blocks. - * @type {number} - * @memberof ChainflipBaasQuoteBoostQuote - */ - numberOfChunks?: number | null; -} - -/** - * Check if a given object implements the ChainflipBaasQuoteBoostQuote interface. - */ -export function instanceOfChainflipBaasQuoteBoostQuote(value: object): boolean { - let isInstance = true; - - return isInstance; -} - -export function ChainflipBaasQuoteBoostQuoteFromJSON(json: any): ChainflipBaasQuoteBoostQuote { - return ChainflipBaasQuoteBoostQuoteFromJSONTyped(json, false); -} - -export function ChainflipBaasQuoteBoostQuoteFromJSONTyped(json: any, ignoreDiscriminator: boolean): ChainflipBaasQuoteBoostQuote { - if ((json === undefined) || (json === null)) { - return json; - } - return { - - 'ingressAsset': !exists(json, 'ingressAsset') ? undefined : json['ingressAsset'], - 'ingressAmount': !exists(json, 'ingressAmount') ? undefined : json['ingressAmount'], - 'ingressAmountNative': !exists(json, 'ingressAmountNative') ? undefined : json['ingressAmountNative'], - 'egressAsset': !exists(json, 'egressAsset') ? undefined : json['egressAsset'], - 'egressAmount': !exists(json, 'egressAmount') ? undefined : json['egressAmount'], - 'egressAmountNative': !exists(json, 'egressAmountNative') ? undefined : json['egressAmountNative'], - 'includedFees': !exists(json, 'includedFees') ? undefined : ((json['includedFees'] as Array).map(ChainflipBaasQuoteQuoteFeeFromJSON)), - 'lowLiquidityWarning': !exists(json, 'lowLiquidityWarning') ? undefined : json['lowLiquidityWarning'], - 'poolInfo': !exists(json, 'poolInfo') ? undefined : ((json['poolInfo'] as Array).map(ChainflipBaasQuotePoolInfoFromJSON)), - 'estimatedDurationSeconds': !exists(json, 'estimatedDurationSeconds') ? undefined : json['estimatedDurationSeconds'], - 'estimatedBoostFeeBps': !exists(json, 'estimatedBoostFeeBps') ? undefined : json['estimatedBoostFeeBps'], - 'chunkIntervalBlocks': !exists(json, 'chunkIntervalBlocks') ? undefined : json['chunkIntervalBlocks'], - 'numberOfChunks': !exists(json, 'numberOfChunks') ? undefined : json['numberOfChunks'], - }; -} - -export function ChainflipBaasQuoteBoostQuoteToJSON(value?: ChainflipBaasQuoteBoostQuote | null): any { - if (value === undefined) { - return undefined; - } - if (value === null) { - return null; - } - return { - - 'ingressAsset': value.ingressAsset, - 'ingressAmount': value.ingressAmount, - 'egressAsset': value.egressAsset, - 'poolInfo': value.poolInfo === undefined ? undefined : ((value.poolInfo as Array).map(ChainflipBaasQuotePoolInfoToJSON)), - 'chunkIntervalBlocks': value.chunkIntervalBlocks, - 'numberOfChunks': value.numberOfChunks, - }; -} - diff --git a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasQuotePoolFee.ts b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasQuotePoolFee.ts deleted file mode 100644 index cb881a98c03..00000000000 --- a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasQuotePoolFee.ts +++ /dev/null @@ -1,82 +0,0 @@ -// @ts-nocheck -/* tslint:disable */ -/* eslint-disable */ -/** - * Chainflip Broker as a Service - * Run your own Chainflip Broker without any hassle. - * - * The version of the OpenAPI document: v1 - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - -import { exists, mapValues } from '../runtime'; -/** - * - * @export - * @interface ChainflipBaasQuotePoolFee - */ -export interface ChainflipBaasQuotePoolFee { - /** - * The asset the fee is processed in. - * @type {string} - * @memberof ChainflipBaasQuotePoolFee - */ - asset?: string | null; - /** - * The fee amount. - * @type {number} - * @memberof ChainflipBaasQuotePoolFee - */ - amount?: number; - /** - * The fee amount in native units. - * @type {string} - * @memberof ChainflipBaasQuotePoolFee - */ - amountNative?: string; -} - -/** - * Check if a given object implements the ChainflipBaasQuotePoolFee interface. - */ -export function instanceOfChainflipBaasQuotePoolFee(value: object): boolean { - let isInstance = true; - - return isInstance; -} - -export function ChainflipBaasQuotePoolFeeFromJSON(json: any): ChainflipBaasQuotePoolFee { - return ChainflipBaasQuotePoolFeeFromJSONTyped(json, false); -} - -export function ChainflipBaasQuotePoolFeeFromJSONTyped(json: any, ignoreDiscriminator: boolean): ChainflipBaasQuotePoolFee { - if ((json === undefined) || (json === null)) { - return json; - } - return { - - 'asset': !exists(json, 'asset') ? undefined : json['asset'], - 'amount': !exists(json, 'amount') ? undefined : json['amount'], - 'amountNative': !exists(json, 'amountNative') ? undefined : json['amountNative'], - }; -} - -export function ChainflipBaasQuotePoolFeeToJSON(value?: ChainflipBaasQuotePoolFee | null): any { - if (value === undefined) { - return undefined; - } - if (value === null) { - return null; - } - return { - - 'asset': value.asset, - 'amount': value.amount, - 'amountNative': value.amountNative, - }; -} - diff --git a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasQuotePoolInfo.ts b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasQuotePoolInfo.ts deleted file mode 100644 index 6f499f241ea..00000000000 --- a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasQuotePoolInfo.ts +++ /dev/null @@ -1,89 +0,0 @@ -// @ts-nocheck -/* tslint:disable */ -/* eslint-disable */ -/** - * Chainflip Broker as a Service - * Run your own Chainflip Broker without any hassle. - * - * The version of the OpenAPI document: v1 - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - -import { exists, mapValues } from '../runtime'; -import type { ChainflipBaasQuotePoolFee } from './ChainflipBaasQuotePoolFee'; -import { - ChainflipBaasQuotePoolFeeFromJSON, - ChainflipBaasQuotePoolFeeFromJSONTyped, - ChainflipBaasQuotePoolFeeToJSON, -} from './ChainflipBaasQuotePoolFee'; - -/** - * - * @export - * @interface ChainflipBaasQuotePoolInfo - */ -export interface ChainflipBaasQuotePoolInfo { - /** - * The base asset of the pool involved. - * @type {string} - * @memberof ChainflipBaasQuotePoolInfo - */ - baseAsset?: string; - /** - * The quote asset of the pool involved. - * @type {string} - * @memberof ChainflipBaasQuotePoolInfo - */ - quoteAsset?: string; - /** - * - * @type {ChainflipBaasQuotePoolFee} - * @memberof ChainflipBaasQuotePoolInfo - */ - fee?: ChainflipBaasQuotePoolFee; -} - -/** - * Check if a given object implements the ChainflipBaasQuotePoolInfo interface. - */ -export function instanceOfChainflipBaasQuotePoolInfo(value: object): boolean { - let isInstance = true; - - return isInstance; -} - -export function ChainflipBaasQuotePoolInfoFromJSON(json: any): ChainflipBaasQuotePoolInfo { - return ChainflipBaasQuotePoolInfoFromJSONTyped(json, false); -} - -export function ChainflipBaasQuotePoolInfoFromJSONTyped(json: any, ignoreDiscriminator: boolean): ChainflipBaasQuotePoolInfo { - if ((json === undefined) || (json === null)) { - return json; - } - return { - - 'baseAsset': !exists(json, 'baseAsset') ? undefined : json['baseAsset'], - 'quoteAsset': !exists(json, 'quoteAsset') ? undefined : json['quoteAsset'], - 'fee': !exists(json, 'fee') ? undefined : ChainflipBaasQuotePoolFeeFromJSON(json['fee']), - }; -} - -export function ChainflipBaasQuotePoolInfoToJSON(value?: ChainflipBaasQuotePoolInfo | null): any { - if (value === undefined) { - return undefined; - } - if (value === null) { - return null; - } - return { - - 'baseAsset': value.baseAsset, - 'quoteAsset': value.quoteAsset, - 'fee': ChainflipBaasQuotePoolFeeToJSON(value.fee), - }; -} - diff --git a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusAffiliateBroker.ts b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusAffiliateBroker.ts deleted file mode 100644 index ef32761419a..00000000000 --- a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusAffiliateBroker.ts +++ /dev/null @@ -1,72 +0,0 @@ -// @ts-nocheck -/* tslint:disable */ -/* eslint-disable */ -/** - * Chainflip Broker as a Service - * Run your own Chainflip Broker without any hassle. - * - * The version of the OpenAPI document: v1 - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - -import { exists, mapValues } from '../runtime'; -/** - * - * @export - * @interface ChainflipBaasStatusAffiliateBroker - */ -export interface ChainflipBaasStatusAffiliateBroker { - /** - * - * @type {string} - * @memberof ChainflipBaasStatusAffiliateBroker - */ - readonly account?: string; - /** - * - * @type {number} - * @memberof ChainflipBaasStatusAffiliateBroker - */ - readonly commissionBps?: number; -} - -/** - * Check if a given object implements the ChainflipBaasStatusAffiliateBroker interface. - */ -export function instanceOfChainflipBaasStatusAffiliateBroker(value: object): boolean { - let isInstance = true; - - return isInstance; -} - -export function ChainflipBaasStatusAffiliateBrokerFromJSON(json: any): ChainflipBaasStatusAffiliateBroker { - return ChainflipBaasStatusAffiliateBrokerFromJSONTyped(json, false); -} - -export function ChainflipBaasStatusAffiliateBrokerFromJSONTyped(json: any, ignoreDiscriminator: boolean): ChainflipBaasStatusAffiliateBroker { - if ((json === undefined) || (json === null)) { - return json; - } - return { - - 'account': !exists(json, 'account') ? undefined : json['account'], - 'commissionBps': !exists(json, 'commissionBps') ? undefined : json['commissionBps'], - }; -} - -export function ChainflipBaasStatusAffiliateBrokerToJSON(value?: ChainflipBaasStatusAffiliateBroker | null): any { - if (value === undefined) { - return undefined; - } - if (value === null) { - return null; - } - return { - - }; -} - diff --git a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusBoost.ts b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusBoost.ts deleted file mode 100644 index a32ef9aad81..00000000000 --- a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusBoost.ts +++ /dev/null @@ -1,114 +0,0 @@ -// @ts-nocheck -/* tslint:disable */ -/* eslint-disable */ -/** - * Chainflip Broker as a Service - * Run your own Chainflip Broker without any hassle. - * - * The version of the OpenAPI document: v1 - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - -import { exists, mapValues } from '../runtime'; -/** - * - * @export - * @interface ChainflipBaasStatusBoost - */ -export interface ChainflipBaasStatusBoost { - /** - * - * @type {number} - * @memberof ChainflipBaasStatusBoost - */ - readonly maximumBoostFeeBps?: number; - /** - * - * @type {number} - * @memberof ChainflipBaasStatusBoost - */ - readonly effectiveBoostFeeBps?: number | null; - /** - * - * @type {number} - * @memberof ChainflipBaasStatusBoost - */ - readonly boostedAt?: number | null; - /** - * - * @type {Date} - * @memberof ChainflipBaasStatusBoost - */ - readonly boostedAtDate?: Date | null; - /** - * - * @type {string} - * @memberof ChainflipBaasStatusBoost - */ - readonly boostedBlockIndex?: string | null; - /** - * - * @type {number} - * @memberof ChainflipBaasStatusBoost - */ - readonly skippedAt?: number | null; - /** - * - * @type {Date} - * @memberof ChainflipBaasStatusBoost - */ - readonly skippedAtDate?: Date | null; - /** - * - * @type {string} - * @memberof ChainflipBaasStatusBoost - */ - readonly skippedBlockIndex?: string | null; -} - -/** - * Check if a given object implements the ChainflipBaasStatusBoost interface. - */ -export function instanceOfChainflipBaasStatusBoost(value: object): boolean { - let isInstance = true; - - return isInstance; -} - -export function ChainflipBaasStatusBoostFromJSON(json: any): ChainflipBaasStatusBoost { - return ChainflipBaasStatusBoostFromJSONTyped(json, false); -} - -export function ChainflipBaasStatusBoostFromJSONTyped(json: any, ignoreDiscriminator: boolean): ChainflipBaasStatusBoost { - if ((json === undefined) || (json === null)) { - return json; - } - return { - - 'maximumBoostFeeBps': !exists(json, 'maximumBoostFeeBps') ? undefined : json['maximumBoostFeeBps'], - 'effectiveBoostFeeBps': !exists(json, 'effectiveBoostFeeBps') ? undefined : json['effectiveBoostFeeBps'], - 'boostedAt': !exists(json, 'boostedAt') ? undefined : json['boostedAt'], - 'boostedAtDate': !exists(json, 'boostedAtDate') ? undefined : (json['boostedAtDate'] === null ? null : new Date(json['boostedAtDate'])), - 'boostedBlockIndex': !exists(json, 'boostedBlockIndex') ? undefined : json['boostedBlockIndex'], - 'skippedAt': !exists(json, 'skippedAt') ? undefined : json['skippedAt'], - 'skippedAtDate': !exists(json, 'skippedAtDate') ? undefined : (json['skippedAtDate'] === null ? null : new Date(json['skippedAtDate'])), - 'skippedBlockIndex': !exists(json, 'skippedBlockIndex') ? undefined : json['skippedBlockIndex'], - }; -} - -export function ChainflipBaasStatusBoostToJSON(value?: ChainflipBaasStatusBoost | null): any { - if (value === undefined) { - return undefined; - } - if (value === null) { - return null; - } - return { - - }; -} - diff --git a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusCcmParameters.ts b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusCcmParameters.ts deleted file mode 100644 index d029a854f37..00000000000 --- a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusCcmParameters.ts +++ /dev/null @@ -1,79 +0,0 @@ -// @ts-nocheck -/* tslint:disable */ -/* eslint-disable */ -/** - * Chainflip Broker as a Service - * Run your own Chainflip Broker without any hassle. - * - * The version of the OpenAPI document: v1 - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - -import { exists, mapValues } from '../runtime'; -/** - * - * @export - * @interface ChainflipBaasStatusCcmParameters - */ -export interface ChainflipBaasStatusCcmParameters { - /** - * - * @type {string} - * @memberof ChainflipBaasStatusCcmParameters - */ - readonly gasBudget?: string; - /** - * - * @type {string} - * @memberof ChainflipBaasStatusCcmParameters - */ - readonly message?: string; - /** - * - * @type {string} - * @memberof ChainflipBaasStatusCcmParameters - */ - readonly cfParameters?: string | null; -} - -/** - * Check if a given object implements the ChainflipBaasStatusCcmParameters interface. - */ -export function instanceOfChainflipBaasStatusCcmParameters(value: object): boolean { - let isInstance = true; - - return isInstance; -} - -export function ChainflipBaasStatusCcmParametersFromJSON(json: any): ChainflipBaasStatusCcmParameters { - return ChainflipBaasStatusCcmParametersFromJSONTyped(json, false); -} - -export function ChainflipBaasStatusCcmParametersFromJSONTyped(json: any, ignoreDiscriminator: boolean): ChainflipBaasStatusCcmParameters { - if ((json === undefined) || (json === null)) { - return json; - } - return { - - 'gasBudget': !exists(json, 'gasBudget') ? undefined : json['gasBudget'], - 'message': !exists(json, 'message') ? undefined : json['message'], - 'cfParameters': !exists(json, 'cfParameters') ? undefined : json['cfParameters'], - }; -} - -export function ChainflipBaasStatusCcmParametersToJSON(value?: ChainflipBaasStatusCcmParameters | null): any { - if (value === undefined) { - return undefined; - } - if (value === null) { - return null; - } - return { - - }; -} - diff --git a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusChunkInfo.ts b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusChunkInfo.ts deleted file mode 100644 index 32814c5a17f..00000000000 --- a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusChunkInfo.ts +++ /dev/null @@ -1,149 +0,0 @@ -// @ts-nocheck -/* tslint:disable */ -/* eslint-disable */ -/** - * Chainflip Broker as a Service - * Run your own Chainflip Broker without any hassle. - * - * The version of the OpenAPI document: v1 - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - -import { exists, mapValues } from '../runtime'; -/** - * - * @export - * @interface ChainflipBaasStatusChunkInfo - */ -export interface ChainflipBaasStatusChunkInfo { - /** - * - * @type {string} - * @memberof ChainflipBaasStatusChunkInfo - */ - readonly inputAmountNative?: string; - /** - * - * @type {number} - * @memberof ChainflipBaasStatusChunkInfo - */ - readonly inputAmount?: number; - /** - * - * @type {string} - * @memberof ChainflipBaasStatusChunkInfo - */ - readonly intermediateAmountNative?: string | null; - /** - * - * @type {number} - * @memberof ChainflipBaasStatusChunkInfo - */ - readonly intermediateAmount?: number | null; - /** - * - * @type {string} - * @memberof ChainflipBaasStatusChunkInfo - */ - readonly outputAmountNative?: string | null; - /** - * - * @type {number} - * @memberof ChainflipBaasStatusChunkInfo - */ - readonly outputAmount?: number | null; - /** - * - * @type {number} - * @memberof ChainflipBaasStatusChunkInfo - */ - readonly scheduledAt?: number; - /** - * - * @type {Date} - * @memberof ChainflipBaasStatusChunkInfo - */ - readonly scheduledAtDate?: Date; - /** - * - * @type {string} - * @memberof ChainflipBaasStatusChunkInfo - */ - readonly scheduledBlockIndex?: string; - /** - * - * @type {number} - * @memberof ChainflipBaasStatusChunkInfo - */ - readonly executedAt?: number | null; - /** - * - * @type {Date} - * @memberof ChainflipBaasStatusChunkInfo - */ - readonly executedAtDate?: Date | null; - /** - * - * @type {string} - * @memberof ChainflipBaasStatusChunkInfo - */ - readonly executedBlockIndex?: string | null; - /** - * - * @type {number} - * @memberof ChainflipBaasStatusChunkInfo - */ - readonly retryCount?: number; -} - -/** - * Check if a given object implements the ChainflipBaasStatusChunkInfo interface. - */ -export function instanceOfChainflipBaasStatusChunkInfo(value: object): boolean { - let isInstance = true; - - return isInstance; -} - -export function ChainflipBaasStatusChunkInfoFromJSON(json: any): ChainflipBaasStatusChunkInfo { - return ChainflipBaasStatusChunkInfoFromJSONTyped(json, false); -} - -export function ChainflipBaasStatusChunkInfoFromJSONTyped(json: any, ignoreDiscriminator: boolean): ChainflipBaasStatusChunkInfo { - if ((json === undefined) || (json === null)) { - return json; - } - return { - - 'inputAmountNative': !exists(json, 'inputAmountNative') ? undefined : json['inputAmountNative'], - 'inputAmount': !exists(json, 'inputAmount') ? undefined : json['inputAmount'], - 'intermediateAmountNative': !exists(json, 'intermediateAmountNative') ? undefined : json['intermediateAmountNative'], - 'intermediateAmount': !exists(json, 'intermediateAmount') ? undefined : json['intermediateAmount'], - 'outputAmountNative': !exists(json, 'outputAmountNative') ? undefined : json['outputAmountNative'], - 'outputAmount': !exists(json, 'outputAmount') ? undefined : json['outputAmount'], - 'scheduledAt': !exists(json, 'scheduledAt') ? undefined : json['scheduledAt'], - 'scheduledAtDate': !exists(json, 'scheduledAtDate') ? undefined : (new Date(json['scheduledAtDate'])), - 'scheduledBlockIndex': !exists(json, 'scheduledBlockIndex') ? undefined : json['scheduledBlockIndex'], - 'executedAt': !exists(json, 'executedAt') ? undefined : json['executedAt'], - 'executedAtDate': !exists(json, 'executedAtDate') ? undefined : (json['executedAtDate'] === null ? null : new Date(json['executedAtDate'])), - 'executedBlockIndex': !exists(json, 'executedBlockIndex') ? undefined : json['executedBlockIndex'], - 'retryCount': !exists(json, 'retryCount') ? undefined : json['retryCount'], - }; -} - -export function ChainflipBaasStatusChunkInfoToJSON(value?: ChainflipBaasStatusChunkInfo | null): any { - if (value === undefined) { - return undefined; - } - if (value === null) { - return null; - } - return { - - }; -} - diff --git a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusDca.ts b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusDca.ts deleted file mode 100644 index 0f261b0950c..00000000000 --- a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusDca.ts +++ /dev/null @@ -1,95 +0,0 @@ -// @ts-nocheck -/* tslint:disable */ -/* eslint-disable */ -/** - * Chainflip Broker as a Service - * Run your own Chainflip Broker without any hassle. - * - * The version of the OpenAPI document: v1 - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - -import { exists, mapValues } from '../runtime'; -import type { ChainflipBaasStatusChunkInfo } from './ChainflipBaasStatusChunkInfo'; -import { - ChainflipBaasStatusChunkInfoFromJSON, - ChainflipBaasStatusChunkInfoFromJSONTyped, - ChainflipBaasStatusChunkInfoToJSON, -} from './ChainflipBaasStatusChunkInfo'; - -/** - * - * @export - * @interface ChainflipBaasStatusDca - */ -export interface ChainflipBaasStatusDca { - /** - * - * @type {ChainflipBaasStatusChunkInfo} - * @memberof ChainflipBaasStatusDca - */ - lastExecutedChunk?: ChainflipBaasStatusChunkInfo; - /** - * - * @type {ChainflipBaasStatusChunkInfo} - * @memberof ChainflipBaasStatusDca - */ - currentChunk?: ChainflipBaasStatusChunkInfo; - /** - * - * @type {number} - * @memberof ChainflipBaasStatusDca - */ - readonly executedChunks?: number; - /** - * - * @type {number} - * @memberof ChainflipBaasStatusDca - */ - readonly remainingChunks?: number; -} - -/** - * Check if a given object implements the ChainflipBaasStatusDca interface. - */ -export function instanceOfChainflipBaasStatusDca(value: object): boolean { - let isInstance = true; - - return isInstance; -} - -export function ChainflipBaasStatusDcaFromJSON(json: any): ChainflipBaasStatusDca { - return ChainflipBaasStatusDcaFromJSONTyped(json, false); -} - -export function ChainflipBaasStatusDcaFromJSONTyped(json: any, ignoreDiscriminator: boolean): ChainflipBaasStatusDca { - if ((json === undefined) || (json === null)) { - return json; - } - return { - - 'lastExecutedChunk': !exists(json, 'lastExecutedChunk') ? undefined : ChainflipBaasStatusChunkInfoFromJSON(json['lastExecutedChunk']), - 'currentChunk': !exists(json, 'currentChunk') ? undefined : ChainflipBaasStatusChunkInfoFromJSON(json['currentChunk']), - 'executedChunks': !exists(json, 'executedChunks') ? undefined : json['executedChunks'], - 'remainingChunks': !exists(json, 'remainingChunks') ? undefined : json['remainingChunks'], - }; -} - -export function ChainflipBaasStatusDcaToJSON(value?: ChainflipBaasStatusDca | null): any { - if (value === undefined) { - return undefined; - } - if (value === null) { - return null; - } - return { - - 'lastExecutedChunk': ChainflipBaasStatusChunkInfoToJSON(value.lastExecutedChunk), - 'currentChunk': ChainflipBaasStatusChunkInfoToJSON(value.currentChunk), - }; -} - diff --git a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusDcaParameters.ts b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusDcaParameters.ts deleted file mode 100644 index f08cedee1a5..00000000000 --- a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusDcaParameters.ts +++ /dev/null @@ -1,72 +0,0 @@ -// @ts-nocheck -/* tslint:disable */ -/* eslint-disable */ -/** - * Chainflip Broker as a Service - * Run your own Chainflip Broker without any hassle. - * - * The version of the OpenAPI document: v1 - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - -import { exists, mapValues } from '../runtime'; -/** - * - * @export - * @interface ChainflipBaasStatusDcaParameters - */ -export interface ChainflipBaasStatusDcaParameters { - /** - * - * @type {number} - * @memberof ChainflipBaasStatusDcaParameters - */ - readonly numberOfChunks?: number; - /** - * - * @type {number} - * @memberof ChainflipBaasStatusDcaParameters - */ - readonly chunkIntervalBlocks?: number; -} - -/** - * Check if a given object implements the ChainflipBaasStatusDcaParameters interface. - */ -export function instanceOfChainflipBaasStatusDcaParameters(value: object): boolean { - let isInstance = true; - - return isInstance; -} - -export function ChainflipBaasStatusDcaParametersFromJSON(json: any): ChainflipBaasStatusDcaParameters { - return ChainflipBaasStatusDcaParametersFromJSONTyped(json, false); -} - -export function ChainflipBaasStatusDcaParametersFromJSONTyped(json: any, ignoreDiscriminator: boolean): ChainflipBaasStatusDcaParameters { - if ((json === undefined) || (json === null)) { - return json; - } - return { - - 'numberOfChunks': !exists(json, 'numberOfChunks') ? undefined : json['numberOfChunks'], - 'chunkIntervalBlocks': !exists(json, 'chunkIntervalBlocks') ? undefined : json['chunkIntervalBlocks'], - }; -} - -export function ChainflipBaasStatusDcaParametersToJSON(value?: ChainflipBaasStatusDcaParameters | null): any { - if (value === undefined) { - return undefined; - } - if (value === null) { - return null; - } - return { - - }; -} - diff --git a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusDeposit.ts b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusDeposit.ts deleted file mode 100644 index f618fb53344..00000000000 --- a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusDeposit.ts +++ /dev/null @@ -1,143 +0,0 @@ -// @ts-nocheck -/* tslint:disable */ -/* eslint-disable */ -/** - * Chainflip Broker as a Service - * Run your own Chainflip Broker without any hassle. - * - * The version of the OpenAPI document: v1 - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - -import { exists, mapValues } from '../runtime'; -import type { ChainflipBaasStatusFailure } from './ChainflipBaasStatusFailure'; -import { - ChainflipBaasStatusFailureFromJSON, - ChainflipBaasStatusFailureFromJSONTyped, - ChainflipBaasStatusFailureToJSON, -} from './ChainflipBaasStatusFailure'; - -/** - * - * @export - * @interface ChainflipBaasStatusDeposit - */ -export interface ChainflipBaasStatusDeposit { - /** - * - * @type {string} - * @memberof ChainflipBaasStatusDeposit - */ - readonly amountNative?: string; - /** - * - * @type {number} - * @memberof ChainflipBaasStatusDeposit - */ - readonly amount?: number; - /** - * - * @type {string} - * @memberof ChainflipBaasStatusDeposit - */ - readonly transactionReference?: string | null; - /** - * - * @type {number} - * @memberof ChainflipBaasStatusDeposit - */ - readonly transactionConfirmations?: number | null; - /** - * - * @type {number} - * @memberof ChainflipBaasStatusDeposit - */ - readonly witnessedAt?: number | null; - /** - * - * @type {Date} - * @memberof ChainflipBaasStatusDeposit - */ - readonly witnessedAtDate?: Date | null; - /** - * - * @type {string} - * @memberof ChainflipBaasStatusDeposit - */ - readonly witnessedBlockIndex?: string | null; - /** - * - * @type {ChainflipBaasStatusFailure} - * @memberof ChainflipBaasStatusDeposit - */ - failure?: ChainflipBaasStatusFailure; - /** - * - * @type {number} - * @memberof ChainflipBaasStatusDeposit - */ - readonly failedAt?: number | null; - /** - * - * @type {Date} - * @memberof ChainflipBaasStatusDeposit - */ - readonly failedAtDate?: Date | null; - /** - * - * @type {string} - * @memberof ChainflipBaasStatusDeposit - */ - readonly failedBlockIndex?: string | null; -} - -/** - * Check if a given object implements the ChainflipBaasStatusDeposit interface. - */ -export function instanceOfChainflipBaasStatusDeposit(value: object): boolean { - let isInstance = true; - - return isInstance; -} - -export function ChainflipBaasStatusDepositFromJSON(json: any): ChainflipBaasStatusDeposit { - return ChainflipBaasStatusDepositFromJSONTyped(json, false); -} - -export function ChainflipBaasStatusDepositFromJSONTyped(json: any, ignoreDiscriminator: boolean): ChainflipBaasStatusDeposit { - if ((json === undefined) || (json === null)) { - return json; - } - return { - - 'amountNative': !exists(json, 'amountNative') ? undefined : json['amountNative'], - 'amount': !exists(json, 'amount') ? undefined : json['amount'], - 'transactionReference': !exists(json, 'transactionReference') ? undefined : json['transactionReference'], - 'transactionConfirmations': !exists(json, 'transactionConfirmations') ? undefined : json['transactionConfirmations'], - 'witnessedAt': !exists(json, 'witnessedAt') ? undefined : json['witnessedAt'], - 'witnessedAtDate': !exists(json, 'witnessedAtDate') ? undefined : (json['witnessedAtDate'] === null ? null : new Date(json['witnessedAtDate'])), - 'witnessedBlockIndex': !exists(json, 'witnessedBlockIndex') ? undefined : json['witnessedBlockIndex'], - 'failure': !exists(json, 'failure') ? undefined : ChainflipBaasStatusFailureFromJSON(json['failure']), - 'failedAt': !exists(json, 'failedAt') ? undefined : json['failedAt'], - 'failedAtDate': !exists(json, 'failedAtDate') ? undefined : (json['failedAtDate'] === null ? null : new Date(json['failedAtDate'])), - 'failedBlockIndex': !exists(json, 'failedBlockIndex') ? undefined : json['failedBlockIndex'], - }; -} - -export function ChainflipBaasStatusDepositToJSON(value?: ChainflipBaasStatusDeposit | null): any { - if (value === undefined) { - return undefined; - } - if (value === null) { - return null; - } - return { - - 'failure': ChainflipBaasStatusFailureToJSON(value.failure), - }; -} - diff --git a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusDepositChannel.ts b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusDepositChannel.ts deleted file mode 100644 index 7be58f17604..00000000000 --- a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusDepositChannel.ts +++ /dev/null @@ -1,184 +0,0 @@ -// @ts-nocheck -/* tslint:disable */ -/* eslint-disable */ -/** - * Chainflip Broker as a Service - * Run your own Chainflip Broker without any hassle. - * - * The version of the OpenAPI document: v1 - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - -import { exists, mapValues } from '../runtime'; -import type { ChainflipBaasStatusAffiliateBroker } from './ChainflipBaasStatusAffiliateBroker'; -import { - ChainflipBaasStatusAffiliateBrokerFromJSON, - ChainflipBaasStatusAffiliateBrokerFromJSONTyped, - ChainflipBaasStatusAffiliateBrokerToJSON, -} from './ChainflipBaasStatusAffiliateBroker'; -import type { ChainflipBaasStatusDcaParameters } from './ChainflipBaasStatusDcaParameters'; -import { - ChainflipBaasStatusDcaParametersFromJSON, - ChainflipBaasStatusDcaParametersFromJSONTyped, - ChainflipBaasStatusDcaParametersToJSON, -} from './ChainflipBaasStatusDcaParameters'; -import type { ChainflipBaasStatusFillOrKillParameters } from './ChainflipBaasStatusFillOrKillParameters'; -import { - ChainflipBaasStatusFillOrKillParametersFromJSON, - ChainflipBaasStatusFillOrKillParametersFromJSONTyped, - ChainflipBaasStatusFillOrKillParametersToJSON, -} from './ChainflipBaasStatusFillOrKillParameters'; - -/** - * - * @export - * @interface ChainflipBaasStatusDepositChannel - */ -export interface ChainflipBaasStatusDepositChannel { - /** - * - * @type {string} - * @memberof ChainflipBaasStatusDepositChannel - */ - readonly id?: string; - /** - * - * @type {number} - * @memberof ChainflipBaasStatusDepositChannel - */ - readonly createdAt?: number; - /** - * - * @type {Date} - * @memberof ChainflipBaasStatusDepositChannel - */ - readonly createdAtDate?: Date; - /** - * - * @type {number} - * @memberof ChainflipBaasStatusDepositChannel - */ - readonly brokerCommissionBps?: number; - /** - * - * @type {string} - * @memberof ChainflipBaasStatusDepositChannel - */ - readonly depositAddress?: string; - /** - * - * @type {string} - * @memberof ChainflipBaasStatusDepositChannel - */ - readonly sourceChainExpiryBlock?: string; - /** - * - * @type {number} - * @memberof ChainflipBaasStatusDepositChannel - */ - readonly estimatedExpiryTime?: number; - /** - * - * @type {Date} - * @memberof ChainflipBaasStatusDepositChannel - */ - readonly estimatedExpiryDate?: Date; - /** - * - * @type {number} - * @memberof ChainflipBaasStatusDepositChannel - */ - readonly expectedDepositAmount?: number | null; - /** - * - * @type {string} - * @memberof ChainflipBaasStatusDepositChannel - */ - readonly expectedDepositAmountNative?: string | null; - /** - * - * @type {boolean} - * @memberof ChainflipBaasStatusDepositChannel - */ - readonly isExpired?: boolean; - /** - * - * @type {boolean} - * @memberof ChainflipBaasStatusDepositChannel - */ - readonly openedThroughBackend?: boolean; - /** - * - * @type {Array} - * @memberof ChainflipBaasStatusDepositChannel - */ - readonly affiliateBrokers?: Array | null; - /** - * - * @type {ChainflipBaasStatusFillOrKillParameters} - * @memberof ChainflipBaasStatusDepositChannel - */ - fillOrKillParams?: ChainflipBaasStatusFillOrKillParameters; - /** - * - * @type {ChainflipBaasStatusDcaParameters} - * @memberof ChainflipBaasStatusDepositChannel - */ - dcaParams?: ChainflipBaasStatusDcaParameters; -} - -/** - * Check if a given object implements the ChainflipBaasStatusDepositChannel interface. - */ -export function instanceOfChainflipBaasStatusDepositChannel(value: object): boolean { - let isInstance = true; - - return isInstance; -} - -export function ChainflipBaasStatusDepositChannelFromJSON(json: any): ChainflipBaasStatusDepositChannel { - return ChainflipBaasStatusDepositChannelFromJSONTyped(json, false); -} - -export function ChainflipBaasStatusDepositChannelFromJSONTyped(json: any, ignoreDiscriminator: boolean): ChainflipBaasStatusDepositChannel { - if ((json === undefined) || (json === null)) { - return json; - } - return { - - 'id': !exists(json, 'id') ? undefined : json['id'], - 'createdAt': !exists(json, 'createdAt') ? undefined : json['createdAt'], - 'createdAtDate': !exists(json, 'createdAtDate') ? undefined : (new Date(json['createdAtDate'])), - 'brokerCommissionBps': !exists(json, 'brokerCommissionBps') ? undefined : json['brokerCommissionBps'], - 'depositAddress': !exists(json, 'depositAddress') ? undefined : json['depositAddress'], - 'sourceChainExpiryBlock': !exists(json, 'sourceChainExpiryBlock') ? undefined : json['sourceChainExpiryBlock'], - 'estimatedExpiryTime': !exists(json, 'estimatedExpiryTime') ? undefined : json['estimatedExpiryTime'], - 'estimatedExpiryDate': !exists(json, 'estimatedExpiryDate') ? undefined : (new Date(json['estimatedExpiryDate'])), - 'expectedDepositAmount': !exists(json, 'expectedDepositAmount') ? undefined : json['expectedDepositAmount'], - 'expectedDepositAmountNative': !exists(json, 'expectedDepositAmountNative') ? undefined : json['expectedDepositAmountNative'], - 'isExpired': !exists(json, 'isExpired') ? undefined : json['isExpired'], - 'openedThroughBackend': !exists(json, 'openedThroughBackend') ? undefined : json['openedThroughBackend'], - 'affiliateBrokers': !exists(json, 'affiliateBrokers') ? undefined : (json['affiliateBrokers'] === null ? null : (json['affiliateBrokers'] as Array).map(ChainflipBaasStatusAffiliateBrokerFromJSON)), - 'fillOrKillParams': !exists(json, 'fillOrKillParams') ? undefined : ChainflipBaasStatusFillOrKillParametersFromJSON(json['fillOrKillParams']), - 'dcaParams': !exists(json, 'dcaParams') ? undefined : ChainflipBaasStatusDcaParametersFromJSON(json['dcaParams']), - }; -} - -export function ChainflipBaasStatusDepositChannelToJSON(value?: ChainflipBaasStatusDepositChannel | null): any { - if (value === undefined) { - return undefined; - } - if (value === null) { - return null; - } - return { - - 'fillOrKillParams': ChainflipBaasStatusFillOrKillParametersToJSON(value.fillOrKillParams), - 'dcaParams': ChainflipBaasStatusDcaParametersToJSON(value.dcaParams), - }; -} - diff --git a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusEgress.ts b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusEgress.ts deleted file mode 100644 index ab56435015d..00000000000 --- a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusEgress.ts +++ /dev/null @@ -1,150 +0,0 @@ -// @ts-nocheck -/* tslint:disable */ -/* eslint-disable */ -/** - * Chainflip Broker as a Service - * Run your own Chainflip Broker without any hassle. - * - * The version of the OpenAPI document: v1 - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - -import { exists, mapValues } from '../runtime'; -import type { ChainflipBaasStatusFailure } from './ChainflipBaasStatusFailure'; -import { - ChainflipBaasStatusFailureFromJSON, - ChainflipBaasStatusFailureFromJSONTyped, - ChainflipBaasStatusFailureToJSON, -} from './ChainflipBaasStatusFailure'; - -/** - * - * @export - * @interface ChainflipBaasStatusEgress - */ -export interface ChainflipBaasStatusEgress { - /** - * - * @type {string} - * @memberof ChainflipBaasStatusEgress - */ - readonly amountNative?: string; - /** - * - * @type {number} - * @memberof ChainflipBaasStatusEgress - */ - readonly amount?: number; - /** - * - * @type {number} - * @memberof ChainflipBaasStatusEgress - */ - readonly scheduledAt?: number | null; - /** - * - * @type {Date} - * @memberof ChainflipBaasStatusEgress - */ - readonly scheduledAtDate?: Date | null; - /** - * - * @type {string} - * @memberof ChainflipBaasStatusEgress - */ - readonly scheduledBlockIndex?: string | null; - /** - * - * @type {string} - * @memberof ChainflipBaasStatusEgress - */ - readonly transactionReference?: string | null; - /** - * - * @type {number} - * @memberof ChainflipBaasStatusEgress - */ - readonly witnessedAt?: number | null; - /** - * - * @type {string} - * @memberof ChainflipBaasStatusEgress - */ - readonly witnessedBlockIndex?: string | null; - /** - * - * @type {ChainflipBaasStatusFailure} - * @memberof ChainflipBaasStatusEgress - */ - failure?: ChainflipBaasStatusFailure; - /** - * - * @type {number} - * @memberof ChainflipBaasStatusEgress - */ - readonly failedAt?: number | null; - /** - * - * @type {Date} - * @memberof ChainflipBaasStatusEgress - */ - readonly failedAtDate?: Date | null; - /** - * - * @type {string} - * @memberof ChainflipBaasStatusEgress - */ - readonly failedBlockIndex?: string | null; -} - -/** - * Check if a given object implements the ChainflipBaasStatusEgress interface. - */ -export function instanceOfChainflipBaasStatusEgress(value: object): boolean { - let isInstance = true; - - return isInstance; -} - -export function ChainflipBaasStatusEgressFromJSON(json: any): ChainflipBaasStatusEgress { - return ChainflipBaasStatusEgressFromJSONTyped(json, false); -} - -export function ChainflipBaasStatusEgressFromJSONTyped(json: any, ignoreDiscriminator: boolean): ChainflipBaasStatusEgress { - if ((json === undefined) || (json === null)) { - return json; - } - return { - - 'amountNative': !exists(json, 'amountNative') ? undefined : json['amountNative'], - 'amount': !exists(json, 'amount') ? undefined : json['amount'], - 'scheduledAt': !exists(json, 'scheduledAt') ? undefined : json['scheduledAt'], - 'scheduledAtDate': !exists(json, 'scheduledAtDate') ? undefined : (json['scheduledAtDate'] === null ? null : new Date(json['scheduledAtDate'])), - 'scheduledBlockIndex': !exists(json, 'scheduledBlockIndex') ? undefined : json['scheduledBlockIndex'], - 'transactionReference': !exists(json, 'transactionReference') ? undefined : json['transactionReference'], - 'witnessedAt': !exists(json, 'witnessedAt') ? undefined : json['witnessedAt'], - 'witnessedBlockIndex': !exists(json, 'witnessedBlockIndex') ? undefined : json['witnessedBlockIndex'], - 'failure': !exists(json, 'failure') ? undefined : ChainflipBaasStatusFailureFromJSON(json['failure']), - 'failedAt': !exists(json, 'failedAt') ? undefined : json['failedAt'], - 'failedAtDate': !exists(json, 'failedAtDate') ? undefined : (json['failedAtDate'] === null ? null : new Date(json['failedAtDate'])), - 'failedBlockIndex': !exists(json, 'failedBlockIndex') ? undefined : json['failedBlockIndex'], - }; -} - -export function ChainflipBaasStatusEgressToJSON(value?: ChainflipBaasStatusEgress | null): any { - if (value === undefined) { - return undefined; - } - if (value === null) { - return null; - } - return { - - 'failure': ChainflipBaasStatusFailureToJSON(value.failure), - }; -} - diff --git a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusFailure.ts b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusFailure.ts deleted file mode 100644 index 1f2466d474e..00000000000 --- a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusFailure.ts +++ /dev/null @@ -1,101 +0,0 @@ -// @ts-nocheck -/* tslint:disable */ -/* eslint-disable */ -/** - * Chainflip Broker as a Service - * Run your own Chainflip Broker without any hassle. - * - * The version of the OpenAPI document: v1 - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - -import { exists, mapValues } from '../runtime'; -import type { ChainflipBaasStatusReason } from './ChainflipBaasStatusReason'; -import { - ChainflipBaasStatusReasonFromJSON, - ChainflipBaasStatusReasonFromJSONTyped, - ChainflipBaasStatusReasonToJSON, -} from './ChainflipBaasStatusReason'; - -/** - * - * @export - * @interface ChainflipBaasStatusFailure - */ -export interface ChainflipBaasStatusFailure { - /** - * - * @type {number} - * @memberof ChainflipBaasStatusFailure - */ - readonly failedAt?: number; - /** - * - * @type {Date} - * @memberof ChainflipBaasStatusFailure - */ - readonly failedAtDate?: Date; - /** - * - * @type {string} - * @memberof ChainflipBaasStatusFailure - */ - readonly failedBlockIndex?: string; - /** - * - * @type {string} - * @memberof ChainflipBaasStatusFailure - */ - readonly mode?: string; - /** - * - * @type {ChainflipBaasStatusReason} - * @memberof ChainflipBaasStatusFailure - */ - reason?: ChainflipBaasStatusReason; -} - -/** - * Check if a given object implements the ChainflipBaasStatusFailure interface. - */ -export function instanceOfChainflipBaasStatusFailure(value: object): boolean { - let isInstance = true; - - return isInstance; -} - -export function ChainflipBaasStatusFailureFromJSON(json: any): ChainflipBaasStatusFailure { - return ChainflipBaasStatusFailureFromJSONTyped(json, false); -} - -export function ChainflipBaasStatusFailureFromJSONTyped(json: any, ignoreDiscriminator: boolean): ChainflipBaasStatusFailure { - if ((json === undefined) || (json === null)) { - return json; - } - return { - - 'failedAt': !exists(json, 'failedAt') ? undefined : json['failedAt'], - 'failedAtDate': !exists(json, 'failedAtDate') ? undefined : (new Date(json['failedAtDate'])), - 'failedBlockIndex': !exists(json, 'failedBlockIndex') ? undefined : json['failedBlockIndex'], - 'mode': !exists(json, 'mode') ? undefined : json['mode'], - 'reason': !exists(json, 'reason') ? undefined : ChainflipBaasStatusReasonFromJSON(json['reason']), - }; -} - -export function ChainflipBaasStatusFailureToJSON(value?: ChainflipBaasStatusFailure | null): any { - if (value === undefined) { - return undefined; - } - if (value === null) { - return null; - } - return { - - 'reason': ChainflipBaasStatusReasonToJSON(value.reason), - }; -} - diff --git a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusFillOrKillParameters.ts b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusFillOrKillParameters.ts deleted file mode 100644 index 37c8ed3eee7..00000000000 --- a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusFillOrKillParameters.ts +++ /dev/null @@ -1,79 +0,0 @@ -// @ts-nocheck -/* tslint:disable */ -/* eslint-disable */ -/** - * Chainflip Broker as a Service - * Run your own Chainflip Broker without any hassle. - * - * The version of the OpenAPI document: v1 - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - -import { exists, mapValues } from '../runtime'; -/** - * - * @export - * @interface ChainflipBaasStatusFillOrKillParameters - */ -export interface ChainflipBaasStatusFillOrKillParameters { - /** - * - * @type {number} - * @memberof ChainflipBaasStatusFillOrKillParameters - */ - readonly retryDurationBlocks?: number; - /** - * - * @type {string} - * @memberof ChainflipBaasStatusFillOrKillParameters - */ - readonly refundAddress?: string; - /** - * - * @type {string} - * @memberof ChainflipBaasStatusFillOrKillParameters - */ - readonly minimumPrice?: string; -} - -/** - * Check if a given object implements the ChainflipBaasStatusFillOrKillParameters interface. - */ -export function instanceOfChainflipBaasStatusFillOrKillParameters(value: object): boolean { - let isInstance = true; - - return isInstance; -} - -export function ChainflipBaasStatusFillOrKillParametersFromJSON(json: any): ChainflipBaasStatusFillOrKillParameters { - return ChainflipBaasStatusFillOrKillParametersFromJSONTyped(json, false); -} - -export function ChainflipBaasStatusFillOrKillParametersFromJSONTyped(json: any, ignoreDiscriminator: boolean): ChainflipBaasStatusFillOrKillParameters { - if ((json === undefined) || (json === null)) { - return json; - } - return { - - 'retryDurationBlocks': !exists(json, 'retryDurationBlocks') ? undefined : json['retryDurationBlocks'], - 'refundAddress': !exists(json, 'refundAddress') ? undefined : json['refundAddress'], - 'minimumPrice': !exists(json, 'minimumPrice') ? undefined : json['minimumPrice'], - }; -} - -export function ChainflipBaasStatusFillOrKillParametersToJSON(value?: ChainflipBaasStatusFillOrKillParameters | null): any { - if (value === undefined) { - return undefined; - } - if (value === null) { - return null; - } - return { - - }; -} - diff --git a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusPaidFee.ts b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusPaidFee.ts deleted file mode 100644 index b37935c3d3e..00000000000 --- a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusPaidFee.ts +++ /dev/null @@ -1,101 +0,0 @@ -// @ts-nocheck -/* tslint:disable */ -/* eslint-disable */ -/** - * Chainflip Broker as a Service - * Run your own Chainflip Broker without any hassle. - * - * The version of the OpenAPI document: v1 - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - -import { exists, mapValues } from '../runtime'; -/** - * - * @export - * @interface ChainflipBaasStatusPaidFee - */ -export interface ChainflipBaasStatusPaidFee { - /** - * - * @type {string} - * @memberof ChainflipBaasStatusPaidFee - */ - readonly type?: ChainflipBaasStatusPaidFeeTypeEnum; - /** - * - * @type {string} - * @memberof ChainflipBaasStatusPaidFee - */ - readonly asset?: string; - /** - * - * @type {string} - * @memberof ChainflipBaasStatusPaidFee - */ - readonly amountNative?: string; - /** - * - * @type {number} - * @memberof ChainflipBaasStatusPaidFee - */ - readonly amount?: number; -} - - -/** - * @export - */ -export const ChainflipBaasStatusPaidFeeTypeEnum = { - Network: 'network', - Ingress: 'ingress', - Egress: 'egress', - Broker: 'broker', - Boost: 'boost', - Liquidity: 'liquidity' -} as const; -export type ChainflipBaasStatusPaidFeeTypeEnum = typeof ChainflipBaasStatusPaidFeeTypeEnum[keyof typeof ChainflipBaasStatusPaidFeeTypeEnum]; - - -/** - * Check if a given object implements the ChainflipBaasStatusPaidFee interface. - */ -export function instanceOfChainflipBaasStatusPaidFee(value: object): boolean { - let isInstance = true; - - return isInstance; -} - -export function ChainflipBaasStatusPaidFeeFromJSON(json: any): ChainflipBaasStatusPaidFee { - return ChainflipBaasStatusPaidFeeFromJSONTyped(json, false); -} - -export function ChainflipBaasStatusPaidFeeFromJSONTyped(json: any, ignoreDiscriminator: boolean): ChainflipBaasStatusPaidFee { - if ((json === undefined) || (json === null)) { - return json; - } - return { - - 'type': !exists(json, 'type') ? undefined : json['type'], - 'asset': !exists(json, 'asset') ? undefined : json['asset'], - 'amountNative': !exists(json, 'amountNative') ? undefined : json['amountNative'], - 'amount': !exists(json, 'amount') ? undefined : json['amount'], - }; -} - -export function ChainflipBaasStatusPaidFeeToJSON(value?: ChainflipBaasStatusPaidFee | null): any { - if (value === undefined) { - return undefined; - } - if (value === null) { - return null; - } - return { - - }; -} - diff --git a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusReason.ts b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusReason.ts deleted file mode 100644 index 9c9eec84fcd..00000000000 --- a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusReason.ts +++ /dev/null @@ -1,72 +0,0 @@ -// @ts-nocheck -/* tslint:disable */ -/* eslint-disable */ -/** - * Chainflip Broker as a Service - * Run your own Chainflip Broker without any hassle. - * - * The version of the OpenAPI document: v1 - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - -import { exists, mapValues } from '../runtime'; -/** - * - * @export - * @interface ChainflipBaasStatusReason - */ -export interface ChainflipBaasStatusReason { - /** - * - * @type {string} - * @memberof ChainflipBaasStatusReason - */ - readonly code?: string; - /** - * - * @type {string} - * @memberof ChainflipBaasStatusReason - */ - readonly message?: string; -} - -/** - * Check if a given object implements the ChainflipBaasStatusReason interface. - */ -export function instanceOfChainflipBaasStatusReason(value: object): boolean { - let isInstance = true; - - return isInstance; -} - -export function ChainflipBaasStatusReasonFromJSON(json: any): ChainflipBaasStatusReason { - return ChainflipBaasStatusReasonFromJSONTyped(json, false); -} - -export function ChainflipBaasStatusReasonFromJSONTyped(json: any, ignoreDiscriminator: boolean): ChainflipBaasStatusReason { - if ((json === undefined) || (json === null)) { - return json; - } - return { - - 'code': !exists(json, 'code') ? undefined : json['code'], - 'message': !exists(json, 'message') ? undefined : json['message'], - }; -} - -export function ChainflipBaasStatusReasonToJSON(value?: ChainflipBaasStatusReason | null): any { - if (value === undefined) { - return undefined; - } - if (value === null) { - return null; - } - return { - - }; -} - diff --git a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusStatusResponse.ts b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusStatusResponse.ts deleted file mode 100644 index 56004260684..00000000000 --- a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusStatusResponse.ts +++ /dev/null @@ -1,81 +0,0 @@ -// @ts-nocheck -/* tslint:disable */ -/* eslint-disable */ -/** - * Chainflip Broker as a Service - * Run your own Chainflip Broker without any hassle. - * - * The version of the OpenAPI document: v1 - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - -import { exists, mapValues } from '../runtime'; -import type { ChainflipBaasStatusSwapStatus } from './ChainflipBaasStatusSwapStatus'; -import { - ChainflipBaasStatusSwapStatusFromJSON, - ChainflipBaasStatusSwapStatusFromJSONTyped, - ChainflipBaasStatusSwapStatusToJSON, -} from './ChainflipBaasStatusSwapStatus'; - -/** - * - * @export - * @interface ChainflipBaasStatusStatusResponse - */ -export interface ChainflipBaasStatusStatusResponse { - /** - * - * @type {number} - * @memberof ChainflipBaasStatusStatusResponse - */ - id?: number; - /** - * - * @type {ChainflipBaasStatusSwapStatus} - * @memberof ChainflipBaasStatusStatusResponse - */ - status?: ChainflipBaasStatusSwapStatus; -} - -/** - * Check if a given object implements the ChainflipBaasStatusStatusResponse interface. - */ -export function instanceOfChainflipBaasStatusStatusResponse(value: object): boolean { - let isInstance = true; - - return isInstance; -} - -export function ChainflipBaasStatusStatusResponseFromJSON(json: any): ChainflipBaasStatusStatusResponse { - return ChainflipBaasStatusStatusResponseFromJSONTyped(json, false); -} - -export function ChainflipBaasStatusStatusResponseFromJSONTyped(json: any, ignoreDiscriminator: boolean): ChainflipBaasStatusStatusResponse { - if ((json === undefined) || (json === null)) { - return json; - } - return { - - 'id': !exists(json, 'id') ? undefined : json['id'], - 'status': !exists(json, 'status') ? undefined : ChainflipBaasStatusSwapStatusFromJSON(json['status']), - }; -} - -export function ChainflipBaasStatusStatusResponseToJSON(value?: ChainflipBaasStatusStatusResponse | null): any { - if (value === undefined) { - return undefined; - } - if (value === null) { - return null; - } - return { - - 'id': value.id, - 'status': ChainflipBaasStatusSwapStatusToJSON(value.status), - }; -} - diff --git a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusSwap.ts b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusSwap.ts deleted file mode 100644 index 45482daaaf7..00000000000 --- a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusSwap.ts +++ /dev/null @@ -1,167 +0,0 @@ -// @ts-nocheck -/* tslint:disable */ -/* eslint-disable */ -/** - * Chainflip Broker as a Service - * Run your own Chainflip Broker without any hassle. - * - * The version of the OpenAPI document: v1 - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - -import { exists, mapValues } from '../runtime'; -import type { ChainflipBaasStatusChunkInfo } from './ChainflipBaasStatusChunkInfo'; -import { - ChainflipBaasStatusChunkInfoFromJSON, - ChainflipBaasStatusChunkInfoFromJSONTyped, - ChainflipBaasStatusChunkInfoToJSON, -} from './ChainflipBaasStatusChunkInfo'; -import type { ChainflipBaasStatusDca } from './ChainflipBaasStatusDca'; -import { - ChainflipBaasStatusDcaFromJSON, - ChainflipBaasStatusDcaFromJSONTyped, - ChainflipBaasStatusDcaToJSON, -} from './ChainflipBaasStatusDca'; - -/** - * - * @export - * @interface ChainflipBaasStatusSwap - */ -export interface ChainflipBaasStatusSwap { - /** - * - * @type {string} - * @memberof ChainflipBaasStatusSwap - */ - originalInputAmountNative?: string; - /** - * - * @type {number} - * @memberof ChainflipBaasStatusSwap - */ - originalInputAmount?: number; - /** - * - * @type {string} - * @memberof ChainflipBaasStatusSwap - */ - remainingInputAmountNative?: string; - /** - * - * @type {number} - * @memberof ChainflipBaasStatusSwap - */ - remainingInputAmount?: number; - /** - * - * @type {string} - * @memberof ChainflipBaasStatusSwap - */ - swappedInputAmountNative?: string; - /** - * - * @type {number} - * @memberof ChainflipBaasStatusSwap - */ - swappedInputAmount?: number; - /** - * - * @type {string} - * @memberof ChainflipBaasStatusSwap - */ - swappedIntermediateAmountNative?: string; - /** - * - * @type {number} - * @memberof ChainflipBaasStatusSwap - */ - swappedIntermediateAmount?: number; - /** - * - * @type {string} - * @memberof ChainflipBaasStatusSwap - */ - swappedOutputAmountNative?: string; - /** - * - * @type {number} - * @memberof ChainflipBaasStatusSwap - */ - swappedOutputAmount?: number; - /** - * - * @type {ChainflipBaasStatusChunkInfo} - * @memberof ChainflipBaasStatusSwap - */ - regular?: ChainflipBaasStatusChunkInfo; - /** - * - * @type {ChainflipBaasStatusDca} - * @memberof ChainflipBaasStatusSwap - */ - dca?: ChainflipBaasStatusDca; -} - -/** - * Check if a given object implements the ChainflipBaasStatusSwap interface. - */ -export function instanceOfChainflipBaasStatusSwap(value: object): boolean { - let isInstance = true; - - return isInstance; -} - -export function ChainflipBaasStatusSwapFromJSON(json: any): ChainflipBaasStatusSwap { - return ChainflipBaasStatusSwapFromJSONTyped(json, false); -} - -export function ChainflipBaasStatusSwapFromJSONTyped(json: any, ignoreDiscriminator: boolean): ChainflipBaasStatusSwap { - if ((json === undefined) || (json === null)) { - return json; - } - return { - - 'originalInputAmountNative': !exists(json, 'originalInputAmountNative') ? undefined : json['originalInputAmountNative'], - 'originalInputAmount': !exists(json, 'originalInputAmount') ? undefined : json['originalInputAmount'], - 'remainingInputAmountNative': !exists(json, 'remainingInputAmountNative') ? undefined : json['remainingInputAmountNative'], - 'remainingInputAmount': !exists(json, 'remainingInputAmount') ? undefined : json['remainingInputAmount'], - 'swappedInputAmountNative': !exists(json, 'swappedInputAmountNative') ? undefined : json['swappedInputAmountNative'], - 'swappedInputAmount': !exists(json, 'swappedInputAmount') ? undefined : json['swappedInputAmount'], - 'swappedIntermediateAmountNative': !exists(json, 'swappedIntermediateAmountNative') ? undefined : json['swappedIntermediateAmountNative'], - 'swappedIntermediateAmount': !exists(json, 'swappedIntermediateAmount') ? undefined : json['swappedIntermediateAmount'], - 'swappedOutputAmountNative': !exists(json, 'swappedOutputAmountNative') ? undefined : json['swappedOutputAmountNative'], - 'swappedOutputAmount': !exists(json, 'swappedOutputAmount') ? undefined : json['swappedOutputAmount'], - 'regular': !exists(json, 'regular') ? undefined : ChainflipBaasStatusChunkInfoFromJSON(json['regular']), - 'dca': !exists(json, 'dca') ? undefined : ChainflipBaasStatusDcaFromJSON(json['dca']), - }; -} - -export function ChainflipBaasStatusSwapToJSON(value?: ChainflipBaasStatusSwap | null): any { - if (value === undefined) { - return undefined; - } - if (value === null) { - return null; - } - return { - - 'originalInputAmountNative': value.originalInputAmountNative, - 'originalInputAmount': value.originalInputAmount, - 'remainingInputAmountNative': value.remainingInputAmountNative, - 'remainingInputAmount': value.remainingInputAmount, - 'swappedInputAmountNative': value.swappedInputAmountNative, - 'swappedInputAmount': value.swappedInputAmount, - 'swappedIntermediateAmountNative': value.swappedIntermediateAmountNative, - 'swappedIntermediateAmount': value.swappedIntermediateAmount, - 'swappedOutputAmountNative': value.swappedOutputAmountNative, - 'swappedOutputAmount': value.swappedOutputAmount, - 'regular': ChainflipBaasStatusChunkInfoToJSON(value.regular), - 'dca': ChainflipBaasStatusDcaToJSON(value.dca), - }; -} - diff --git a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusSwapStatus.ts b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusSwapStatus.ts deleted file mode 100644 index e8ff95929fa..00000000000 --- a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusSwapStatus.ts +++ /dev/null @@ -1,243 +0,0 @@ -// @ts-nocheck -/* tslint:disable */ -/* eslint-disable */ -/** - * Chainflip Broker as a Service - * Run your own Chainflip Broker without any hassle. - * - * The version of the OpenAPI document: v1 - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - -import { exists, mapValues } from '../runtime'; -import type { ChainflipBaasStatusBoost } from './ChainflipBaasStatusBoost'; -import { - ChainflipBaasStatusBoostFromJSON, - ChainflipBaasStatusBoostFromJSONTyped, - ChainflipBaasStatusBoostToJSON, -} from './ChainflipBaasStatusBoost'; -import type { ChainflipBaasStatusCcmParameters } from './ChainflipBaasStatusCcmParameters'; -import { - ChainflipBaasStatusCcmParametersFromJSON, - ChainflipBaasStatusCcmParametersFromJSONTyped, - ChainflipBaasStatusCcmParametersToJSON, -} from './ChainflipBaasStatusCcmParameters'; -import type { ChainflipBaasStatusDeposit } from './ChainflipBaasStatusDeposit'; -import { - ChainflipBaasStatusDepositFromJSON, - ChainflipBaasStatusDepositFromJSONTyped, - ChainflipBaasStatusDepositToJSON, -} from './ChainflipBaasStatusDeposit'; -import type { ChainflipBaasStatusDepositChannel } from './ChainflipBaasStatusDepositChannel'; -import { - ChainflipBaasStatusDepositChannelFromJSON, - ChainflipBaasStatusDepositChannelFromJSONTyped, - ChainflipBaasStatusDepositChannelToJSON, -} from './ChainflipBaasStatusDepositChannel'; -import type { ChainflipBaasStatusEgress } from './ChainflipBaasStatusEgress'; -import { - ChainflipBaasStatusEgressFromJSON, - ChainflipBaasStatusEgressFromJSONTyped, - ChainflipBaasStatusEgressToJSON, -} from './ChainflipBaasStatusEgress'; -import type { ChainflipBaasStatusPaidFee } from './ChainflipBaasStatusPaidFee'; -import { - ChainflipBaasStatusPaidFeeFromJSON, - ChainflipBaasStatusPaidFeeFromJSONTyped, - ChainflipBaasStatusPaidFeeToJSON, -} from './ChainflipBaasStatusPaidFee'; -import type { ChainflipBaasStatusSwap } from './ChainflipBaasStatusSwap'; -import { - ChainflipBaasStatusSwapFromJSON, - ChainflipBaasStatusSwapFromJSONTyped, - ChainflipBaasStatusSwapToJSON, -} from './ChainflipBaasStatusSwap'; - -/** - * - * @export - * @interface ChainflipBaasStatusSwapStatus - */ -export interface ChainflipBaasStatusSwapStatus { - /** - * - * @type {string} - * @memberof ChainflipBaasStatusSwapStatus - */ - readonly state?: ChainflipBaasStatusSwapStatusStateEnum; - /** - * - * @type {string} - * @memberof ChainflipBaasStatusSwapStatus - */ - readonly swapId?: string; - /** - * - * @type {string} - * @memberof ChainflipBaasStatusSwapStatus - */ - readonly sourceAsset?: string; - /** - * - * @type {string} - * @memberof ChainflipBaasStatusSwapStatus - */ - readonly destinationAsset?: string; - /** - * - * @type {string} - * @memberof ChainflipBaasStatusSwapStatus - */ - readonly destinationAddress?: string; - /** - * - * @type {ChainflipBaasStatusDepositChannel} - * @memberof ChainflipBaasStatusSwapStatus - */ - depositChannel?: ChainflipBaasStatusDepositChannel; - /** - * - * @type {ChainflipBaasStatusCcmParameters} - * @memberof ChainflipBaasStatusSwapStatus - */ - ccmParams?: ChainflipBaasStatusCcmParameters; - /** - * - * @type {ChainflipBaasStatusBoost} - * @memberof ChainflipBaasStatusSwapStatus - */ - boost?: ChainflipBaasStatusBoost; - /** - * - * @type {number} - * @memberof ChainflipBaasStatusSwapStatus - */ - readonly estimatedDurationSeconds?: number | null; - /** - * - * @type {number} - * @memberof ChainflipBaasStatusSwapStatus - */ - readonly sourceChainRequiredBlockConfirmations?: number | null; - /** - * - * @type {Array} - * @memberof ChainflipBaasStatusSwapStatus - */ - readonly fees?: Array | null; - /** - * - * @type {ChainflipBaasStatusDeposit} - * @memberof ChainflipBaasStatusSwapStatus - */ - deposit?: ChainflipBaasStatusDeposit; - /** - * - * @type {ChainflipBaasStatusSwap} - * @memberof ChainflipBaasStatusSwapStatus - */ - swap?: ChainflipBaasStatusSwap; - /** - * - * @type {ChainflipBaasStatusEgress} - * @memberof ChainflipBaasStatusSwapStatus - */ - swapEgress?: ChainflipBaasStatusEgress; - /** - * - * @type {ChainflipBaasStatusEgress} - * @memberof ChainflipBaasStatusSwapStatus - */ - refundEgress?: ChainflipBaasStatusEgress; - /** - * - * @type {number} - * @memberof ChainflipBaasStatusSwapStatus - */ - readonly lastStateChainUpdateAt?: number | null; - /** - * - * @type {Date} - * @memberof ChainflipBaasStatusSwapStatus - */ - readonly lastStateChainUpdateAtDate?: Date | null; -} - - -/** - * @export - */ -export const ChainflipBaasStatusSwapStatusStateEnum = { - Waiting: 'waiting', - Receiving: 'receiving', - Swapping: 'swapping', - Sending: 'sending', - Sent: 'sent', - Completed: 'completed', - Failed: 'failed' -} as const; -export type ChainflipBaasStatusSwapStatusStateEnum = typeof ChainflipBaasStatusSwapStatusStateEnum[keyof typeof ChainflipBaasStatusSwapStatusStateEnum]; - - -/** - * Check if a given object implements the ChainflipBaasStatusSwapStatus interface. - */ -export function instanceOfChainflipBaasStatusSwapStatus(value: object): boolean { - let isInstance = true; - - return isInstance; -} - -export function ChainflipBaasStatusSwapStatusFromJSON(json: any): ChainflipBaasStatusSwapStatus { - return ChainflipBaasStatusSwapStatusFromJSONTyped(json, false); -} - -export function ChainflipBaasStatusSwapStatusFromJSONTyped(json: any, ignoreDiscriminator: boolean): ChainflipBaasStatusSwapStatus { - if ((json === undefined) || (json === null)) { - return json; - } - return { - - 'state': !exists(json, 'state') ? undefined : json['state'], - 'swapId': !exists(json, 'swapId') ? undefined : json['swapId'], - 'sourceAsset': !exists(json, 'sourceAsset') ? undefined : json['sourceAsset'], - 'destinationAsset': !exists(json, 'destinationAsset') ? undefined : json['destinationAsset'], - 'destinationAddress': !exists(json, 'destinationAddress') ? undefined : json['destinationAddress'], - 'depositChannel': !exists(json, 'depositChannel') ? undefined : ChainflipBaasStatusDepositChannelFromJSON(json['depositChannel']), - 'ccmParams': !exists(json, 'ccmParams') ? undefined : ChainflipBaasStatusCcmParametersFromJSON(json['ccmParams']), - 'boost': !exists(json, 'boost') ? undefined : ChainflipBaasStatusBoostFromJSON(json['boost']), - 'estimatedDurationSeconds': !exists(json, 'estimatedDurationSeconds') ? undefined : json['estimatedDurationSeconds'], - 'sourceChainRequiredBlockConfirmations': !exists(json, 'sourceChainRequiredBlockConfirmations') ? undefined : json['sourceChainRequiredBlockConfirmations'], - 'fees': !exists(json, 'fees') ? undefined : (json['fees'] === null ? null : (json['fees'] as Array).map(ChainflipBaasStatusPaidFeeFromJSON)), - 'deposit': !exists(json, 'deposit') ? undefined : ChainflipBaasStatusDepositFromJSON(json['deposit']), - 'swap': !exists(json, 'swap') ? undefined : ChainflipBaasStatusSwapFromJSON(json['swap']), - 'swapEgress': !exists(json, 'swapEgress') ? undefined : ChainflipBaasStatusEgressFromJSON(json['swapEgress']), - 'refundEgress': !exists(json, 'refundEgress') ? undefined : ChainflipBaasStatusEgressFromJSON(json['refundEgress']), - 'lastStateChainUpdateAt': !exists(json, 'lastStateChainUpdateAt') ? undefined : json['lastStateChainUpdateAt'], - 'lastStateChainUpdateAtDate': !exists(json, 'lastStateChainUpdateAtDate') ? undefined : (json['lastStateChainUpdateAtDate'] === null ? null : new Date(json['lastStateChainUpdateAtDate'])), - }; -} - -export function ChainflipBaasStatusSwapStatusToJSON(value?: ChainflipBaasStatusSwapStatus | null): any { - if (value === undefined) { - return undefined; - } - if (value === null) { - return null; - } - return { - - 'depositChannel': ChainflipBaasStatusDepositChannelToJSON(value.depositChannel), - 'ccmParams': ChainflipBaasStatusCcmParametersToJSON(value.ccmParams), - 'boost': ChainflipBaasStatusBoostToJSON(value.boost), - 'deposit': ChainflipBaasStatusDepositToJSON(value.deposit), - 'swap': ChainflipBaasStatusSwapToJSON(value.swap), - 'swapEgress': ChainflipBaasStatusEgressToJSON(value.swapEgress), - 'refundEgress': ChainflipBaasStatusEgressToJSON(value.refundEgress), - }; -} - From 206a337e6b7dd20ddd7b2766ce976b7bd6e46dfc Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Thu, 31 Oct 2024 08:52:47 +0900 Subject: [PATCH 063/127] feat: cleanup --- .../swappers/ChainflipSwapper/models/index.ts | 27 +++---------------- 1 file changed, 3 insertions(+), 24 deletions(-) diff --git a/packages/swapper/src/swappers/ChainflipSwapper/models/index.ts b/packages/swapper/src/swappers/ChainflipSwapper/models/index.ts index 17079e01819..582d409b4cf 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/models/index.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/models/index.ts @@ -1,24 +1,3 @@ -/* tslint:disable */ -/* eslint-disable */ -export * from './ChainflipBaasQuoteBoostQuote'; -export * from './ChainflipBaasQuotePoolFee'; -export * from './ChainflipBaasQuotePoolInfo'; -export * from './ChainflipBaasQuoteQuote'; -export * from './ChainflipBaasQuoteQuoteFee'; -export * from './ChainflipBaasStatusAffiliateBroker'; -export * from './ChainflipBaasStatusBoost'; -export * from './ChainflipBaasStatusCcmParameters'; -export * from './ChainflipBaasStatusChunkInfo'; -export * from './ChainflipBaasStatusDca'; -export * from './ChainflipBaasStatusDcaParameters'; -export * from './ChainflipBaasStatusDeposit'; -export * from './ChainflipBaasStatusDepositChannel'; -export * from './ChainflipBaasStatusEgress'; -export * from './ChainflipBaasStatusFailure'; -export * from './ChainflipBaasStatusFillOrKillParameters'; -export * from './ChainflipBaasStatusPaidFee'; -export * from './ChainflipBaasStatusReason'; -export * from './ChainflipBaasStatusStatusResponse'; -export * from './ChainflipBaasStatusSwap'; -export * from './ChainflipBaasStatusSwapStatus'; -export * from './ChainflipBaasSwapDepositAddress'; +export * from './ChainflipBaasQuoteQuote' +export * from './ChainflipBaasQuoteQuoteFee' +export * from './ChainflipBaasSwapDepositAddress' From 7cfe7c26118c97ce8f573c80993bf3dc30f3a008 Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Thu, 31 Oct 2024 09:18:15 +0900 Subject: [PATCH 064/127] feat: cleanup some more --- .../swapperApi/getUnsignedEvmTransaction.ts | 58 +++++++++---------- packages/swapper/src/utils.ts | 17 +++++- 2 files changed, 43 insertions(+), 32 deletions(-) diff --git a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts index 9f84d03d00b..df0ea0c9743 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts @@ -1,10 +1,10 @@ import { fromAssetId, fromChainId } from '@shapeshiftoss/caip' -import { getErc20Data, getFees } from '@shapeshiftoss/chain-adapters/dist/evm/utils' -import type { KnownChainIds } from '@shapeshiftoss/types' +import { FeeDataKey, type GetFeeDataInput } from '@shapeshiftoss/chain-adapters' +import type { EvmChainId, KnownChainIds } from '@shapeshiftoss/types' import type { AxiosError } from 'axios' import type { EvmTransactionRequest, GetUnsignedEvmTransactionArgs } from '../../../types' -import { isExecutableTradeQuote } from '../../../utils' +import { isExecutableTradeQuote, isToken } from '../../../utils' import { CHAINFLIP_BAAS_COMMISSION, chainIdToChainflipNetwork } from '../constants' import type { ChainflipBaasSwapDepositAddress } from '../models' import { chainflipService } from '../utils/chainflipService' @@ -14,7 +14,6 @@ export const getUnsignedEvmTransaction = async ({ chainId, from, tradeQuote, - supportsEIP1559, assertGetEvmChainAdapter, config, }: GetUnsignedEvmTransactionArgs): Promise => { @@ -68,48 +67,45 @@ export const getUnsignedEvmTransaction = async ({ const depositAddress = swapResponse.address! const { assetReference } = fromAssetId(step.sellAsset.assetId) - const isTokenSend = !!assetReference + const isTokenSend = isToken(step.sellAsset.assetId) - const adapter = assertGetEvmChainAdapter(chainId) + const adapter = assertGetEvmChainAdapter(step.sellAsset.chainId) - const fees = await getFees({ - adapter, + const getFeeDataInput: GetFeeDataInput = { to: depositAddress, - from, - value: (isTokenSend - ? 0n - : BigInt(step.sellAmountIncludingProtocolFeesCryptoBaseUnit) - ).toString(), - data: await getErc20Data( - depositAddress, - step.sellAmountIncludingProtocolFeesCryptoBaseUnit, - assetReference, - ), - supportsEIP1559, - }) + value: step.sellAmountIncludingProtocolFeesCryptoBaseUnit, + chainSpecific: { + from, + contractAddress: assetReference, + data: undefined, + }, + sendMax: false, + } + const feeData = await adapter.getFeeData(getFeeDataInput) + const fees = feeData[FeeDataKey.Average] - const tx = await adapter.buildSendApiTransaction({ + const unsignedTxInput = await adapter.buildSendApiTransaction({ to: depositAddress, from, value: step.sellAmountIncludingProtocolFeesCryptoBaseUnit, accountNumber: step.accountNumber, chainSpecific: { gasLimit: getGasLimit(sellChainflipChainKey), - contractAddress: assetReference, - maxFeePerGas: fees.maxFeePerGas!, - maxPriorityFeePerGas: fees.maxPriorityFeePerGas!, + contractAddress: isTokenSend ? assetReference : undefined, + maxFeePerGas: fees.chainSpecific.maxFeePerGas!, + maxPriorityFeePerGas: fees.chainSpecific.maxPriorityFeePerGas!, }, }) return { chainId: Number(fromChainId(chainId).chainReference), - data: tx.data, - to: tx.to, + data: unsignedTxInput.data, + to: unsignedTxInput.to, from, - value: tx.value, - gasLimit: tx.gasLimit, - maxFeePerGas: tx.maxFeePerGas, - maxPriorityFeePerGas: tx.maxPriorityFeePerGas, - gasPrice: tx.gasPrice, + value: unsignedTxInput.value, + gasLimit: unsignedTxInput.gasLimit, + maxFeePerGas: unsignedTxInput.maxFeePerGas, + maxPriorityFeePerGas: unsignedTxInput.maxPriorityFeePerGas, + gasPrice: unsignedTxInput.gasPrice, } } diff --git a/packages/swapper/src/utils.ts b/packages/swapper/src/utils.ts index 52188396fa6..811e705a46e 100644 --- a/packages/swapper/src/utils.ts +++ b/packages/swapper/src/utils.ts @@ -1,4 +1,4 @@ -import type { AccountId, AssetId, ChainId } from '@shapeshiftoss/caip' +import { type AccountId, type AssetId, type ChainId, fromAssetId } from '@shapeshiftoss/caip' import type { EvmChainAdapter } from '@shapeshiftoss/chain-adapters' import type { Asset } from '@shapeshiftoss/types' import { evm, TxStatus } from '@shapeshiftoss/unchained-client' @@ -289,3 +289,18 @@ export const getRate = ({ export const isExecutableTradeQuote = (quote: TradeQuote): quote is TradeQuoteWithReceiveAddress => !!quote.receiveAddress + +export const isToken = (assetId: AssetId) => { + switch (fromAssetId(assetId).assetNamespace) { + case 'erc20': + case 'erc721': + case 'erc1155': + case 'bep20': + case 'bep721': + case 'bep1155': + case 'token': + return true + default: + return false + } +} From c2def520b607d3c7d71705a0c6d17e4f0ad9cc8c Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Thu, 31 Oct 2024 09:32:44 +0900 Subject: [PATCH 065/127] feat: more prgorammatic --- .../src/swappers/ChainflipSwapper/constants.ts | 10 ---------- .../swapperApi/getUnsignedEvmTransaction.ts | 16 +++++++++++----- .../ChainflipSwapper/utils/getEvmTxFees.ts | 5 +++-- .../swappers/ChainflipSwapper/utils/helpers.ts | 10 +--------- 4 files changed, 15 insertions(+), 26 deletions(-) diff --git a/packages/swapper/src/swappers/ChainflipSwapper/constants.ts b/packages/swapper/src/swappers/ChainflipSwapper/constants.ts index 839f9ab00da..3856282bed5 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/constants.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/constants.ts @@ -52,16 +52,6 @@ export const chainIdToChainflipNetwork: Partial> = [KnownChainIds.SolanaMainnet]: 'sol', } -// TODO: Verify with chainflip if this are the correct values -export const assetGasLimits: Partial> = { - 'eth.eth': '34000', - 'flip.eth': '52000', - 'usdc.eth': '63000', - 'usdt.eth': '70000', - 'eth.arb': '100000', - 'usdc.arb': '100000', -} - export const CHAINFLIP_SUPPORTED_CHAIN_IDS: SupportedChainIds = { sell: ChainflipSupportedChainIds as unknown as ChainId[], buy: ChainflipSupportedChainIds as unknown as ChainId[], diff --git a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts index df0ea0c9743..89c14821916 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts @@ -8,7 +8,6 @@ import { isExecutableTradeQuote, isToken } from '../../../utils' import { CHAINFLIP_BAAS_COMMISSION, chainIdToChainflipNetwork } from '../constants' import type { ChainflipBaasSwapDepositAddress } from '../models' import { chainflipService } from '../utils/chainflipService' -import { getGasLimit } from '../utils/helpers' export const getUnsignedEvmTransaction = async ({ chainId, @@ -16,6 +15,7 @@ export const getUnsignedEvmTransaction = async ({ tradeQuote, assertGetEvmChainAdapter, config, + supportsEIP1559, }: GetUnsignedEvmTransactionArgs): Promise => { if (!isExecutableTradeQuote(tradeQuote)) throw Error('Unable to execute trade') @@ -76,7 +76,7 @@ export const getUnsignedEvmTransaction = async ({ value: step.sellAmountIncludingProtocolFeesCryptoBaseUnit, chainSpecific: { from, - contractAddress: assetReference, + contractAddress: isTokenSend ? assetReference : undefined, data: undefined, }, sendMax: false, @@ -90,10 +90,16 @@ export const getUnsignedEvmTransaction = async ({ value: step.sellAmountIncludingProtocolFeesCryptoBaseUnit, accountNumber: step.accountNumber, chainSpecific: { - gasLimit: getGasLimit(sellChainflipChainKey), + gasLimit: fees.chainSpecific.gasLimit, contractAddress: isTokenSend ? assetReference : undefined, - maxFeePerGas: fees.chainSpecific.maxFeePerGas!, - maxPriorityFeePerGas: fees.chainSpecific.maxPriorityFeePerGas!, + ...(supportsEIP1559 + ? { + maxFeePerGas: fees.chainSpecific.maxFeePerGas!, + maxPriorityFeePerGas: fees.chainSpecific.maxPriorityFeePerGas!, + } + : { + gasPrice: fees.chainSpecific.gasPrice, + }), }, }) diff --git a/packages/swapper/src/swappers/ChainflipSwapper/utils/getEvmTxFees.ts b/packages/swapper/src/swappers/ChainflipSwapper/utils/getEvmTxFees.ts index 0e1768bdf77..41ebbcd334c 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/utils/getEvmTxFees.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/utils/getEvmTxFees.ts @@ -1,7 +1,7 @@ import type { EvmChainAdapter } from '@shapeshiftoss/chain-adapters' import { evm } from '@shapeshiftoss/chain-adapters' -import { getGasLimit } from './helpers' +import { THOR_EVM_GAS_LIMIT } from '../../ThorchainSwapper/utils/constants' type GetEvmTxFeesArgs = { adapter: EvmChainAdapter @@ -14,7 +14,8 @@ export const getEvmTxFees = async (args: GetEvmTxFeesArgs): Promise => { const { average } = await adapter.getGasFeeData() - const gasLimit = getGasLimit(args.sendAsset) + // That's not THOR but this should do the trick - overestimated effectively + const gasLimit = THOR_EVM_GAS_LIMIT return evm.calcNetworkFeeCryptoBaseUnit({ ...average, diff --git a/packages/swapper/src/swappers/ChainflipSwapper/utils/helpers.ts b/packages/swapper/src/swappers/ChainflipSwapper/utils/helpers.ts index 86543cfcb79..75f6dd12bfd 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/utils/helpers.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/utils/helpers.ts @@ -1,11 +1,7 @@ import { type AssetId, type ChainId } from '@shapeshiftoss/caip' import type { ChainflipSupportedChainId } from '../constants' -import { - assetGasLimits, - ChainflipSupportedAssetIdsByChainId, - ChainflipSupportedChainIds, -} from '../constants' +import { ChainflipSupportedAssetIdsByChainId, ChainflipSupportedChainIds } from '../constants' export const isSupportedChainId = (chainId: ChainId): chainId is ChainflipSupportedChainId => { return ChainflipSupportedChainIds.includes(chainId as ChainflipSupportedChainId) @@ -19,7 +15,3 @@ export const isSupportedAssetId = ( assetId, ) } - -export const getGasLimit = (chainflipAsset: string) => { - return chainflipAsset in assetGasLimits ? assetGasLimits[chainflipAsset]! : '100000' -} From 5ef016959f1415b4e64c8fa7b798795bcfa11edf Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Thu, 31 Oct 2024 09:34:41 +0900 Subject: [PATCH 066/127] feat: clean diff up --- packages/swapper/src/constants.ts | 71 ++++++++++++++++--------------- 1 file changed, 36 insertions(+), 35 deletions(-) diff --git a/packages/swapper/src/constants.ts b/packages/swapper/src/constants.ts index d8e5f902bdc..5c7b85e0c24 100644 --- a/packages/swapper/src/constants.ts +++ b/packages/swapper/src/constants.ts @@ -42,16 +42,23 @@ export const swappers: Record< | (SwapperApi & Swapper & { supportedChainIds: SupportedChainIds; pollingInterval: number }) | undefined > = { - [SwapperName.ArbitrumBridge]: { - ...arbitrumBridgeSwapper, - ...arbitrumBridgeApi, - supportedChainIds: ARBITRUM_BRIDGE_SUPPORTED_CHAIN_IDS, + [SwapperName.LIFI]: { + ...lifiSwapper, + ...lifiApi, + supportedChainIds: LIFI_SUPPORTED_CHAIN_IDS, + pollingInterval: LIFI_GET_TRADE_QUOTE_POLLING_INTERVAL, + }, + [SwapperName.Thorchain]: { + ...thorchainSwapper, + ...thorchainApi, + supportedChainIds: THORCHAIN_SUPPORTED_CHAIN_IDS, pollingInterval: DEFAULT_GET_TRADE_QUOTE_POLLING_INTERVAL, }, - [SwapperName.Chainflip]: { - ...chainflipSwapper, - ...chainflipApi, - supportedChainIds: CHAINFLIP_SUPPORTED_CHAIN_IDS, + [SwapperName.Zrx]: { + ...zrxSwapper, + ...zrxApi, + supportedChainIds: ZRX_SUPPORTED_CHAIN_IDS, + pollingInterval: DEFAULT_GET_TRADE_QUOTE_POLLING_INTERVAL, }, [SwapperName.CowSwap]: { @@ -60,11 +67,11 @@ export const swappers: Record< supportedChainIds: COW_SWAP_SUPPORTED_CHAIN_IDS, pollingInterval: DEFAULT_GET_TRADE_QUOTE_POLLING_INTERVAL, }, - [SwapperName.LIFI]: { - ...lifiSwapper, - ...lifiApi, - supportedChainIds: LIFI_SUPPORTED_CHAIN_IDS, - pollingInterval: LIFI_GET_TRADE_QUOTE_POLLING_INTERVAL, + [SwapperName.ArbitrumBridge]: { + ...arbitrumBridgeSwapper, + ...arbitrumBridgeApi, + supportedChainIds: ARBITRUM_BRIDGE_SUPPORTED_CHAIN_IDS, + pollingInterval: DEFAULT_GET_TRADE_QUOTE_POLLING_INTERVAL, }, [SwapperName.Portals]: { ...portalsSwapper, @@ -72,16 +79,10 @@ export const swappers: Record< supportedChainIds: PORTALS_SUPPORTED_CHAIN_IDS, pollingInterval: DEFAULT_GET_TRADE_QUOTE_POLLING_INTERVAL, }, - [SwapperName.Thorchain]: { - ...thorchainSwapper, - ...thorchainApi, - supportedChainIds: THORCHAIN_SUPPORTED_CHAIN_IDS, - pollingInterval: DEFAULT_GET_TRADE_QUOTE_POLLING_INTERVAL, - }, - [SwapperName.Zrx]: { - ...zrxSwapper, - ...zrxApi, - supportedChainIds: ZRX_SUPPORTED_CHAIN_IDS, + [SwapperName.Chainflip]: { + ...chainflipSwapper, + ...chainflipApi, + supportedChainIds: CHAINFLIP_SUPPORTED_CHAIN_IDS, pollingInterval: DEFAULT_GET_TRADE_QUOTE_POLLING_INTERVAL, }, [SwapperName.Test]: undefined, @@ -89,33 +90,33 @@ export const swappers: Record< // Slippage defaults. Don't export these to ensure the getDefaultSlippageDecimalPercentageForSwapper helper function is used. const DEFAULT_SLIPPAGE_DECIMAL_PERCENTAGE = '0.002' // .2% -const DEFAULT_ARBITRUM_BRIDGE_SLIPPAGE_DECIMAL_PERCENTAGE = '0' // no slippage for Arbitrum Bridge, so no slippage tolerance -const DEFAULT_CHAINFLIP_SLIPPAGE_DECIMAL_PERCENTAGE = '0.02' // 2% const DEFAULT_COWSWAP_SLIPPAGE_DECIMAL_PERCENTAGE = '0.005' // .5% -const DEFAULT_LIFI_SLIPPAGE_DECIMAL_PERCENTAGE = '0.005' // .5% const DEFAULT_PORTALS_SLIPPAGE_DECIMAL_PERCENTAGE = '0.01' // 1% +const DEFAULT_LIFI_SLIPPAGE_DECIMAL_PERCENTAGE = '0.005' // .5% const DEFAULT_THOR_SLIPPAGE_DECIMAL_PERCENTAGE = '0.01' // 1% +const DEFAULT_ARBITRUM_BRIDGE_SLIPPAGE_DECIMAL_PERCENTAGE = '0' // no slippage for Arbitrum Bridge, so no slippage tolerance +const DEFAULT_CHAINFLIP_SLIPPAGE_DECIMAL_PERCENTAGE = '0.02' // 2% export const getDefaultSlippageDecimalPercentageForSwapper = ( swapperName?: SwapperName, ): string => { if (swapperName === undefined) return DEFAULT_SLIPPAGE_DECIMAL_PERCENTAGE switch (swapperName) { - case SwapperName.ArbitrumBridge: - return DEFAULT_ARBITRUM_BRIDGE_SLIPPAGE_DECIMAL_PERCENTAGE - case SwapperName.Chainflip: - return DEFAULT_CHAINFLIP_SLIPPAGE_DECIMAL_PERCENTAGE - case SwapperName.CowSwap: - return DEFAULT_COWSWAP_SLIPPAGE_DECIMAL_PERCENTAGE + case SwapperName.Zrx: + case SwapperName.Test: + return DEFAULT_SLIPPAGE_DECIMAL_PERCENTAGE case SwapperName.LIFI: return DEFAULT_LIFI_SLIPPAGE_DECIMAL_PERCENTAGE + case SwapperName.CowSwap: + return DEFAULT_COWSWAP_SLIPPAGE_DECIMAL_PERCENTAGE case SwapperName.Portals: return DEFAULT_PORTALS_SLIPPAGE_DECIMAL_PERCENTAGE case SwapperName.Thorchain: return DEFAULT_THOR_SLIPPAGE_DECIMAL_PERCENTAGE - case SwapperName.Zrx: - case SwapperName.Test: - return DEFAULT_SLIPPAGE_DECIMAL_PERCENTAGE + case SwapperName.ArbitrumBridge: + return DEFAULT_ARBITRUM_BRIDGE_SLIPPAGE_DECIMAL_PERCENTAGE + case SwapperName.Chainflip: + return DEFAULT_CHAINFLIP_SLIPPAGE_DECIMAL_PERCENTAGE default: assertUnreachable(swapperName) } From 2e77080ba0cffb55c2c2a3df1701e74f44161611 Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Thu, 31 Oct 2024 09:51:27 +0900 Subject: [PATCH 067/127] feat: cleanup consts --- packages/caip/src/constants.ts | 14 +++++-- .../swappers/ChainflipSwapper/constants.ts | 42 ++++++++----------- 2 files changed, 27 insertions(+), 29 deletions(-) diff --git a/packages/caip/src/constants.ts b/packages/caip/src/constants.ts index 433f4601d36..6ea029a0147 100644 --- a/packages/caip/src/constants.ts +++ b/packages/caip/src/constants.ts @@ -17,16 +17,22 @@ export const arbitrumNovaAssetId: AssetId = 'eip155:42170/slip44:60' export const baseAssetId: AssetId = 'eip155:8453/slip44:60' export const solAssetId: AssetId = 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/slip44:501' +export const foxatarAssetId: AssetId = + 'eip155:137/erc721:0x2e727c425a11ce6b8819b3004db332c12d2af2a2' + +export const foxyAssetId: AssetId = 'eip155:1/erc20:0xdc49108ce5c57bc3408c3a5e95f3d864ec386ed3' export const foxOnGnosisAssetId: AssetId = 'eip155:100/erc20:0x21a42669643f45bc0e086b8fc2ed70c23d67509d' export const foxOnArbitrumOneAssetId: AssetId = 'eip155:42161/erc20:0xf929de51d91c77e42f5090069e0ad7a09e513c73' export const foxAssetId: AssetId = 'eip155:1/erc20:0xc770eefad204b5180df6a14ee197d99d808ee52d' -export const foxatarAssetId: AssetId = - 'eip155:137/erc721:0x2e727c425a11ce6b8819b3004db332c12d2af2a2' -export const foxyAssetId: AssetId = 'eip155:1/erc20:0xdc49108ce5c57bc3408c3a5e95f3d864ec386ed3' - export const usdtAssetId: AssetId = 'eip155:1/erc20:0xdac17f958d2ee523a2206206994597c13d831ec7' +export const usdcAssetId: AssetId = 'eip155:1/erc20:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' +export const usdcOnArbitrumOneAssetId: AssetId = + 'eip155:42161/erc20:0xaf88d065e77c8cc2239327c5edb3a432268e5831' +export const usdcOnSolanaAssetId: AssetId = + 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/token:EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v' +export const flipAssetId: AssetId = 'eip155:1/erc20:0x826180541412d574cf1336d22c0c0a287822678a' export const cosmosAssetId: AssetId = 'cosmos:cosmoshub-4/slip44:118' export const thorchainAssetId: AssetId = 'cosmos:thorchain-1/slip44:931' diff --git a/packages/swapper/src/swappers/ChainflipSwapper/constants.ts b/packages/swapper/src/swappers/ChainflipSwapper/constants.ts index 3856282bed5..34c9b37b801 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/constants.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/constants.ts @@ -1,25 +1,22 @@ -import type { AssetId, ChainId } from '@shapeshiftoss/caip' +import { + arbitrumAssetId, + type AssetId, + btcAssetId, + type ChainId, + ethAssetId, + flipAssetId, + solAssetId, + usdcAssetId, + usdcOnArbitrumOneAssetId, + usdcOnSolanaAssetId, + usdtAssetId, +} from '@shapeshiftoss/caip' import type { Asset } from '@shapeshiftoss/types' import { KnownChainIds } from '@shapeshiftoss/types' import type { SupportedChainIds, SwapSource } from '../../types' import { SwapperName } from '../../types' -const ETHEREUM_ETH_ASSET_ID: AssetId = 'eip155:1/slip44:60' -const ETHEREUM_FLIP_ASSET_ID: AssetId = 'eip155:1/erc20:0x826180541412d574cf1336d22c0c0a287822678a' -const ETHEREUM_USDC_ASSET_ID: AssetId = 'eip155:1/erc20:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' -const ETHEREUM_USDT_ASSET_ID: AssetId = 'eip155:1/erc20:0xdac17f958d2ee523a2206206994597c13d831ec7' - -const ARBITRUM_ETH_ASSET_ID: AssetId = 'eip155:42161/slip44:60' -const ARBITRUM_USDC_ASSET_ID: AssetId = - 'eip155:42161/erc20:0xaf88d065e77c8cc2239327c5edb3a432268e5831' - -const BITCOIN_BTC_ASSET_ID: AssetId = 'bip122:000000000019d6689c085ae165831e93/slip44:0' - -const SOLANA_SOL_ASSET_ID: AssetId = 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/slip44:501' -const SOLANA_USDC_ASSET_ID: AssetId = - 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/token:EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v' - export const CHAINFLIP_REGULAR_QUOTE = 'regular' export const CHAINFLIP_DCA_QUOTE = 'dca' export const CHAINFLIP_BAAS_COMMISSION = 5 @@ -34,15 +31,10 @@ export const ChainflipSupportedChainIds = [ export type ChainflipSupportedChainId = (typeof ChainflipSupportedChainIds)[number] export const ChainflipSupportedAssetIdsByChainId: Partial> = { - [KnownChainIds.EthereumMainnet]: [ - ETHEREUM_ETH_ASSET_ID, - ETHEREUM_FLIP_ASSET_ID, - ETHEREUM_USDC_ASSET_ID, - ETHEREUM_USDT_ASSET_ID, - ], - [KnownChainIds.ArbitrumMainnet]: [ARBITRUM_ETH_ASSET_ID, ARBITRUM_USDC_ASSET_ID], - [KnownChainIds.BitcoinMainnet]: [BITCOIN_BTC_ASSET_ID], - [KnownChainIds.SolanaMainnet]: [SOLANA_SOL_ASSET_ID, SOLANA_USDC_ASSET_ID], + [KnownChainIds.EthereumMainnet]: [ethAssetId, flipAssetId, usdcAssetId, usdtAssetId], + [KnownChainIds.ArbitrumMainnet]: [arbitrumAssetId, usdcOnArbitrumOneAssetId], + [KnownChainIds.BitcoinMainnet]: [btcAssetId], + [KnownChainIds.SolanaMainnet]: [solAssetId, usdcOnSolanaAssetId], } export const chainIdToChainflipNetwork: Partial> = { From c32b3700b8bcfa56fbd8e20ccf100c262fdb1858 Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Thu, 31 Oct 2024 09:54:31 +0900 Subject: [PATCH 068/127] feat: consistency --- packages/swapper/src/constants.ts | 2 +- .../ChainflipSwapper/{ChainflipSwapperApi.ts => endpoints.ts} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename packages/swapper/src/swappers/ChainflipSwapper/{ChainflipSwapperApi.ts => endpoints.ts} (100%) diff --git a/packages/swapper/src/constants.ts b/packages/swapper/src/constants.ts index 5c7b85e0c24..9a60ff3745d 100644 --- a/packages/swapper/src/constants.ts +++ b/packages/swapper/src/constants.ts @@ -4,8 +4,8 @@ import { arbitrumBridgeSwapper } from './swappers/ArbitrumBridgeSwapper/Arbitrum import { arbitrumBridgeApi } from './swappers/ArbitrumBridgeSwapper/endpoints' import { ARBITRUM_BRIDGE_SUPPORTED_CHAIN_IDS } from './swappers/ArbitrumBridgeSwapper/utils/constants' import { chainflipSwapper } from './swappers/ChainflipSwapper/ChainflipSwapper' -import { chainflipApi } from './swappers/ChainflipSwapper/ChainflipSwapperApi' import { CHAINFLIP_SUPPORTED_CHAIN_IDS } from './swappers/ChainflipSwapper/constants' +import { chainflipApi } from './swappers/ChainflipSwapper/endpoints' import { cowSwapper } from './swappers/CowSwapper/CowSwapper' import { cowApi } from './swappers/CowSwapper/endpoints' import { COW_SWAP_SUPPORTED_CHAIN_IDS } from './swappers/CowSwapper/utils/constants' diff --git a/packages/swapper/src/swappers/ChainflipSwapper/ChainflipSwapperApi.ts b/packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts similarity index 100% rename from packages/swapper/src/swappers/ChainflipSwapper/ChainflipSwapperApi.ts rename to packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts From 9a10db417f525617f04297eab5632939a5309490 Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Thu, 31 Oct 2024 10:03:12 +0900 Subject: [PATCH 069/127] feat: stopping point --- .env.base | 2 +- .env.dev | 2 ++ .../swappers/ChainflipSwapper/endpoints.ts | 20 +++++++++++++++++-- .../swapperApi/checkTradeStatus.ts | 18 ----------------- .../swapperApi/getTradeQuote.ts | 7 ++++--- 5 files changed, 25 insertions(+), 24 deletions(-) delete mode 100644 packages/swapper/src/swappers/ChainflipSwapper/swapperApi/checkTradeStatus.ts diff --git a/.env.base b/.env.base index 1a593d62b77..ae1629923ba 100644 --- a/.env.base +++ b/.env.base @@ -60,7 +60,7 @@ REACT_APP_FEATURE_READ_ONLY_ASSETS=true # swapper feature flags - other .env files will override these REACT_APP_FEATURE_CHAINFLIP=true -REACT_APP_FEATURE_CHAINFLIP_DCA=true +REACT_APP_FEATURE_CHAINFLIP_DCA=false REACT_APP_FEATURE_COWSWAP=true REACT_APP_FEATURE_LIFI_SWAP=true REACT_APP_FEATURE_THOR_SWAP=true diff --git a/.env.dev b/.env.dev index bd1c54c4273..17d18086db9 100644 --- a/.env.dev +++ b/.env.dev @@ -1,5 +1,7 @@ # feature flags REACT_APP_FEATURE_PUBLIC_TRADE_ROUTE=true +REACT_APP_FEATURE_CHAINFLIP=true +REACT_APP_FEATURE_CHAINFLIP_DCA=false # logging REACT_APP_REDUX_WINDOW=false diff --git a/packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts b/packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts index bd7768d1b88..b1fb4671119 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts @@ -1,5 +1,7 @@ +import { TxStatus } from '@shapeshiftoss/unchained-client' +import type { InterpolationOptions } from 'node-polyglot' + import type { SwapperApi } from '../../types' -import { checkTradeStatus } from './swapperApi/checkTradeStatus' import { getTradeQuote } from './swapperApi/getTradeQuote' import { getUnsignedEvmTransaction } from './swapperApi/getUnsignedEvmTransaction' import { getUnsignedUtxoTransaction } from './swapperApi/getUnsignedUtxoTransaction' @@ -8,5 +10,19 @@ export const chainflipApi: SwapperApi = { getTradeQuote, getUnsignedEvmTransaction, getUnsignedUtxoTransaction, - checkTradeStatus, + checkTradeStatus: async ( + // @ts-ignore TODO(gomes): implement me + input, + ): Promise<{ + status: TxStatus + buyTxHash: string | undefined + message: string | [string, InterpolationOptions] | undefined + }> => { + // TODO(gomes): implement me + return { + buyTxHash: undefined, + status: TxStatus.Unknown, + message: undefined, + } + }, } diff --git a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/checkTradeStatus.ts b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/checkTradeStatus.ts deleted file mode 100644 index 53c4893f1ef..00000000000 --- a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/checkTradeStatus.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { TxStatus } from '@shapeshiftoss/unchained-client' -import type { InterpolationOptions } from 'node-polyglot' - -export const checkTradeStatus = async ( - // @ts-ignore unimplemented yet - input, -): Promise<{ - status: TxStatus - buyTxHash: string | undefined - message: string | [string, InterpolationOptions] | undefined -}> => { - // TODO: Implement - return { - buyTxHash: undefined, - status: TxStatus.Unknown, - message: undefined, - } -} diff --git a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts index d1452bcaa7a..bcac51b7bdc 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts @@ -54,7 +54,7 @@ export const getTradeQuote = async ( if (accountNumber === undefined) { return Err( makeSwapErrorRight({ - message: `unsupported accountNumber`, + message: `accountNumber is required`, code: TradeQuoteError.UnknownError, }), ) @@ -243,7 +243,8 @@ export const getTradeQuote = async ( const isStreaming = singleQuoteResponse.type === CHAINFLIP_DCA_QUOTE if (isStreaming && !deps.config.REACT_APP_FEATURE_CHAINFLIP_DCA) { - // Streaming swaps are not enabled yet + // DCA currently disabled - Streaming swap logic is very much tied to THOR currently and will deserve its own PR to generalize + // Even if we manage to get DCA swaps to execute, we wouldn't manage to properly poll with current web THOR-centric arch continue } @@ -317,7 +318,7 @@ export const getTradeQuote = async ( buyAsset, sellAsset, accountNumber, - allowanceContract: '0x0', // Chainflip does not use contracts + allowanceContract: '0x0', // Chainflip does not use contracts - all Txs are sends estimatedExecutionTimeMs: singleQuoteResponse.estimatedDurationSeconds! * 1000, }, ], From 19f5fcd69407332e26a64432c2ec616ec42af56c Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Thu, 31 Oct 2024 10:04:05 +0900 Subject: [PATCH 070/127] feat: false in base --- .env.base | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.env.base b/.env.base index ae1629923ba..71571448f21 100644 --- a/.env.base +++ b/.env.base @@ -59,7 +59,7 @@ REACT_APP_FEATURE_DYNAMIC_LP_ASSETS=false REACT_APP_FEATURE_READ_ONLY_ASSETS=true # swapper feature flags - other .env files will override these -REACT_APP_FEATURE_CHAINFLIP=true +REACT_APP_FEATURE_CHAINFLIP=false REACT_APP_FEATURE_CHAINFLIP_DCA=false REACT_APP_FEATURE_COWSWAP=true REACT_APP_FEATURE_LIFI_SWAP=true From 311136665840bef169c6a2e36e007a605d8de237 Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Thu, 31 Oct 2024 10:07:35 +0900 Subject: [PATCH 071/127] feat: stopping point for real this time --- packages/swapper/src/swappers/ChainflipSwapper/constants.ts | 2 +- .../swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts | 4 ++-- .../swapperApi/getUnsignedEvmTransaction.ts | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/swapper/src/swappers/ChainflipSwapper/constants.ts b/packages/swapper/src/swappers/ChainflipSwapper/constants.ts index 34c9b37b801..5ac6f5ced73 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/constants.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/constants.ts @@ -37,7 +37,7 @@ export const ChainflipSupportedAssetIdsByChainId: Partial> = { +export const chainIdToChainflipNetwork: Partial> = { [KnownChainIds.EthereumMainnet]: 'eth', [KnownChainIds.ArbitrumMainnet]: 'arb', [KnownChainIds.BitcoinMainnet]: 'btc', diff --git a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts index bcac51b7bdc..0bea273a585 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts @@ -101,10 +101,10 @@ export const getTradeQuote = async ( } const sellChainflipChainKey = `${sellAsset.symbol.toLowerCase()}.${ - chainIdToChainflipNetwork[sellAsset.chainId as KnownChainIds] + chainIdToChainflipNetwork[sellAsset.chainId] }` const buyChainflipChainKey = `${buyAsset.symbol.toLowerCase()}.${ - chainIdToChainflipNetwork[buyAsset.chainId as KnownChainIds] + chainIdToChainflipNetwork[buyAsset.chainId] }` const brokerUrl = deps.config.REACT_APP_CHAINFLIP_API_URL diff --git a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts index 89c14821916..dbf21b9b9a7 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts @@ -1,6 +1,6 @@ import { fromAssetId, fromChainId } from '@shapeshiftoss/caip' import { FeeDataKey, type GetFeeDataInput } from '@shapeshiftoss/chain-adapters' -import type { EvmChainId, KnownChainIds } from '@shapeshiftoss/types' +import type { EvmChainId } from '@shapeshiftoss/types' import type { AxiosError } from 'axios' import type { EvmTransactionRequest, GetUnsignedEvmTransactionArgs } from '../../../types' @@ -24,10 +24,10 @@ export const getUnsignedEvmTransaction = async ({ const step = tradeQuote.steps[0] const sellChainflipChainKey = `${step.sellAsset.symbol.toLowerCase()}.${ - chainIdToChainflipNetwork[step.sellAsset.chainId as KnownChainIds] + chainIdToChainflipNetwork[step.sellAsset.chainId] }` const buyChainflipChainKey = `${step.buyAsset.symbol.toLowerCase()}.${ - chainIdToChainflipNetwork[step.buyAsset.chainId as KnownChainIds] + chainIdToChainflipNetwork[step.buyAsset.chainId] }` // Subtract the BaaS fee to end up at the final displayed commissionBps From 820283bf2ed7588f9468744838d003aa69993400 Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Thu, 31 Oct 2024 10:10:27 +0900 Subject: [PATCH 072/127] fix: lint --- .../src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts index 0bea273a585..7c5847cf6a4 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts @@ -1,6 +1,5 @@ import type { AssetId } from '@shapeshiftoss/caip' import { CHAIN_NAMESPACE, fromAssetId } from '@shapeshiftoss/caip' -import type { KnownChainIds } from '@shapeshiftoss/types' import type { Result } from '@sniptt/monads' import { Err, Ok } from '@sniptt/monads' import type { AxiosError } from 'axios' From ddd13399c744fe63236731a62638f6e83304cbfe Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Mon, 4 Nov 2024 10:16:37 +0900 Subject: [PATCH 073/127] fix: ci --- .../src/swappers/ChainflipSwapper/endpoints.ts | 8 +++++--- .../ChainflipSwapper/swapperApi/getTradeQuote.ts | 13 ++++++++----- .../swapperApi/getUnsignedEvmTransaction.ts | 4 +++- .../swapperApi/getUnsignedUtxoTransaction.ts | 5 ++++- 4 files changed, 20 insertions(+), 10 deletions(-) diff --git a/packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts b/packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts index b1fb4671119..76957622bd8 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts @@ -8,11 +8,12 @@ import { getUnsignedUtxoTransaction } from './swapperApi/getUnsignedUtxoTransact export const chainflipApi: SwapperApi = { getTradeQuote, + // @ts-ignore TODO(gomes): this won't work with the public trade routes flag on, split me once we got this working + getTradeRate: undefined, getUnsignedEvmTransaction, getUnsignedUtxoTransaction, - checkTradeStatus: async ( - // @ts-ignore TODO(gomes): implement me - input, + checkTradeStatus: ( + _input, ): Promise<{ status: TxStatus buyTxHash: string | undefined @@ -20,6 +21,7 @@ export const chainflipApi: SwapperApi = { }> => { // TODO(gomes): implement me return { + // @ts-ignore TODO(gomes): implement me buyTxHash: undefined, status: TxStatus.Unknown, message: undefined, diff --git a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts index 7c5847cf6a4..8fdb045c5e9 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts @@ -7,7 +7,7 @@ import { v4 as uuid } from 'uuid' import { getDefaultSlippageDecimalPercentageForSwapper } from '../../../constants' import type { - GetTradeQuoteInput, + CommonTradeQuoteInput, GetUtxoTradeQuoteInput, SwapErrorRight, SwapperDeps, @@ -38,7 +38,7 @@ import { getUtxoTxFees } from '../utils/getUtxoTxFees' import { isSupportedAssetId, isSupportedChainId } from '../utils/helpers' export const getTradeQuote = async ( - input: GetTradeQuoteInput, + input: CommonTradeQuoteInput, deps: SwapperDeps, ): Promise> => { const { @@ -154,6 +154,7 @@ export const getTradeQuote = async ( switch (chainNamespace) { case CHAIN_NAMESPACE.Evm: { const sellAdapter = deps.assertGetEvmChainAdapter(sellAsset.chainId) + // TODO(gomes): double check dis correct return await getEvmTxFees({ adapter: sellAdapter, supportsEIP1559: (input as GetEvmTradeQuoteInput).supportsEIP1559, @@ -164,6 +165,7 @@ export const getTradeQuote = async ( case CHAIN_NAMESPACE.Utxo: { const sellAdapter = deps.assertGetUtxoChainAdapter(sellAsset.chainId) const publicKey = (input as GetUtxoTradeQuoteInput).xpub! + // TODO(gomes): double check dis correct return await getUtxoTxFees({ sellAmountCryptoBaseUnit: sellAmount, sellAdapter, @@ -171,13 +173,14 @@ export const getTradeQuote = async ( }) } - case CHAIN_NAMESPACE.Solana: { + // TODO(gomes): Cosmos SDK too + case CHAIN_NAMESPACE.CosmosSdk: + case CHAIN_NAMESPACE.Solana: + default: { // TODO: Solana gas calc return undefined } } - - return undefined } const getFeeAsset = (fee: ChainflipBaasQuoteQuoteFee) => { diff --git a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts index dbf21b9b9a7..d314bf48d7c 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts @@ -4,7 +4,7 @@ import type { EvmChainId } from '@shapeshiftoss/types' import type { AxiosError } from 'axios' import type { EvmTransactionRequest, GetUnsignedEvmTransactionArgs } from '../../../types' -import { isExecutableTradeQuote, isToken } from '../../../utils' +import { isExecutableTradeQuote, isExecutableTradeStep, isToken } from '../../../utils' import { CHAINFLIP_BAAS_COMMISSION, chainIdToChainflipNetwork } from '../constants' import type { ChainflipBaasSwapDepositAddress } from '../models' import { chainflipService } from '../utils/chainflipService' @@ -84,6 +84,8 @@ export const getUnsignedEvmTransaction = async ({ const feeData = await adapter.getFeeData(getFeeDataInput) const fees = feeData[FeeDataKey.Average] + if (!isExecutableTradeStep(step)) throw Error('Unable to execute trade step') + const unsignedTxInput = await adapter.buildSendApiTransaction({ to: depositAddress, from, diff --git a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedUtxoTransaction.ts b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedUtxoTransaction.ts index d32b5b72510..597b7be8377 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedUtxoTransaction.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedUtxoTransaction.ts @@ -3,7 +3,7 @@ import type { KnownChainIds } from '@shapeshiftoss/types' import type { AxiosError } from 'axios' import type { GetUnsignedUtxoTransactionArgs, UtxoFeeData } from '../../../types' -import { isExecutableTradeQuote } from '../../../utils' +import { isExecutableTradeQuote, isExecutableTradeStep } from '../../../utils' import { CHAINFLIP_BAAS_COMMISSION, chainIdToChainflipNetwork } from '../constants' import type { ChainflipBaasSwapDepositAddress } from '../models' import { chainflipService } from '../utils/chainflipService' @@ -21,6 +21,9 @@ export const getUnsignedUtxoTransaction = async ({ const apiKey = config.REACT_APP_CHAINFLIP_API_KEY const step = tradeQuote.steps[0] + + if (!isExecutableTradeStep(step)) throw Error('Unable to execute step') + const sellChainflipChainKey = `${step.sellAsset.symbol.toLowerCase()}.${ chainIdToChainflipNetwork[step.sellAsset.chainId as KnownChainIds] }` From 1c1b7111b876594179a43d3d090dd11e8a56d423 Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Mon, 4 Nov 2024 11:34:09 +0900 Subject: [PATCH 074/127] feat: split quotes/rates --- .../swappers/ChainflipSwapper/endpoints.ts | 5 +-- .../swapperApi/getTradeQuote.ts | 42 ++++++++++++++----- 2 files changed, 34 insertions(+), 13 deletions(-) diff --git a/packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts b/packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts index 76957622bd8..f1eec6f22fb 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts @@ -2,14 +2,13 @@ import { TxStatus } from '@shapeshiftoss/unchained-client' import type { InterpolationOptions } from 'node-polyglot' import type { SwapperApi } from '../../types' -import { getTradeQuote } from './swapperApi/getTradeQuote' +import { getTradeQuote, getTradeRate } from './swapperApi/getTradeQuote' import { getUnsignedEvmTransaction } from './swapperApi/getUnsignedEvmTransaction' import { getUnsignedUtxoTransaction } from './swapperApi/getUnsignedUtxoTransaction' export const chainflipApi: SwapperApi = { getTradeQuote, - // @ts-ignore TODO(gomes): this won't work with the public trade routes flag on, split me once we got this working - getTradeRate: undefined, + getTradeRate, getUnsignedEvmTransaction, getUnsignedUtxoTransaction, checkTradeStatus: ( diff --git a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts index 8fdb045c5e9..2af6f0a93e5 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts @@ -8,10 +8,12 @@ import { v4 as uuid } from 'uuid' import { getDefaultSlippageDecimalPercentageForSwapper } from '../../../constants' import type { CommonTradeQuoteInput, + GetTradeRateInput, GetUtxoTradeQuoteInput, SwapErrorRight, SwapperDeps, TradeQuote, + TradeRate, } from '../../../types' import { type GetEvmTradeQuoteInput, @@ -37,7 +39,7 @@ import { getEvmTxFees } from '../utils/getEvmTxFees' import { getUtxoTxFees } from '../utils/getUtxoTxFees' import { isSupportedAssetId, isSupportedChainId } from '../utils/helpers' -export const getTradeQuote = async ( +const _getTradeQuote = async ( input: CommonTradeQuoteInput, deps: SwapperDeps, ): Promise> => { @@ -50,15 +52,6 @@ export const getTradeQuote = async ( affiliateBps: commissionBps, } = input - if (accountNumber === undefined) { - return Err( - makeSwapErrorRight({ - message: `accountNumber is required`, - code: TradeQuoteError.UnknownError, - }), - ) - } - if (!isSupportedChainId(sellAsset.chainId)) { return Err( makeSwapErrorRight({ @@ -331,3 +324,32 @@ export const getTradeQuote = async ( return Ok(quotes) } + +// This isn't a mistake. A trade rate *is* a trade quote. Chainflip doesn't really have a notion of a trade quote, +// they do have a notion of a "swap" (which we effectively only use to get the deposit address), which is irrelevant to the notion of quote vs. rate +export const getTradeRate = async ( + input: GetTradeRateInput, + deps: SwapperDeps, +): Promise> => { + const rates = await _getTradeQuote(input as unknown as CommonTradeQuoteInput, deps) + return rates as Result +} + +export const getTradeQuote = async ( + input: CommonTradeQuoteInput, + deps: SwapperDeps, +): Promise> => { + const { accountNumber } = input + + if (accountNumber === undefined) { + return Err( + makeSwapErrorRight({ + message: `accountNumber is required`, + code: TradeQuoteError.UnknownError, + }), + ) + } + + const quotes = await _getTradeQuote(input, deps) + return quotes +} From 3172d80ba37be251c0c72d8c4759d759826debf5 Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Mon, 4 Nov 2024 11:40:44 +0900 Subject: [PATCH 075/127] feat: cleanup --- .../swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts index 2af6f0a93e5..1f25c186ef3 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts @@ -166,13 +166,11 @@ const _getTradeQuote = async ( }) } - // TODO(gomes): Cosmos SDK too - case CHAIN_NAMESPACE.CosmosSdk: + // TODO(gomes): Solana support case CHAIN_NAMESPACE.Solana: - default: { - // TODO: Solana gas calc return undefined - } + default: + throw new Error('Unsupported chainNamespace') } } From 388b4dc8e61c8c1aa091d22bb43eccb444526257 Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Mon, 4 Nov 2024 13:42:34 +0900 Subject: [PATCH 076/127] feat: trade status --- .../swappers/ChainflipSwapper/endpoints.ts | 185 +++++++++++++++++- .../models/ChainflipBaasStatusEgress.ts | 149 ++++++++++++++ .../utils/chainflipService.ts | 2 +- 3 files changed, 325 insertions(+), 11 deletions(-) create mode 100644 packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusEgress.ts diff --git a/packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts b/packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts index f1eec6f22fb..8700f072bbc 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts @@ -1,28 +1,193 @@ +import { fromAssetId, fromChainId } from '@shapeshiftoss/caip' +import type { GetFeeDataInput } from '@shapeshiftoss/chain-adapters' +import { FeeDataKey } from '@shapeshiftoss/chain-adapters' +import type { EvmChainId } from '@shapeshiftoss/types' import { TxStatus } from '@shapeshiftoss/unchained-client' +import type { AxiosError } from 'axios' import type { InterpolationOptions } from 'node-polyglot' -import type { SwapperApi } from '../../types' +import type { EvmTransactionRequest, GetUnsignedEvmTransactionArgs, SwapperApi } from '../../types' +import { isExecutableTradeQuote, isExecutableTradeStep, isToken } from '../../utils' +import { CHAINFLIP_BAAS_COMMISSION, chainIdToChainflipNetwork } from './constants' +import type { ChainflipBaasStatusEgress } from './models/ChainflipBaasStatusEgress' +import type { ChainflipBaasSwapDepositAddress } from './models/ChainflipBaasSwapDepositAddress' import { getTradeQuote, getTradeRate } from './swapperApi/getTradeQuote' -import { getUnsignedEvmTransaction } from './swapperApi/getUnsignedEvmTransaction' import { getUnsignedUtxoTransaction } from './swapperApi/getUnsignedUtxoTransaction' +import { chainflipService } from './utils/chainflipService' + +// Non-exhaustive +type ChainFlipStatus = { + status: { + state: 'waiting' | 'receiving' | 'swapping' | 'sending' | 'sent' | 'completed' | 'failed' + swapEgress?: ChainflipBaasStatusEgress + } +} + +// Persists the ID so we can look it up later when checking the status +const tradeQuoteMetadata: Map = new Map() export const chainflipApi: SwapperApi = { getTradeQuote, getTradeRate, - getUnsignedEvmTransaction, + getUnsignedEvmTransaction: async ({ + chainId, + from, + tradeQuote, + assertGetEvmChainAdapter, + config, + supportsEIP1559, + }: GetUnsignedEvmTransactionArgs): Promise => { + if (!isExecutableTradeQuote(tradeQuote)) throw Error('Unable to execute trade') + + const brokerUrl = config.REACT_APP_CHAINFLIP_API_URL + const apiKey = config.REACT_APP_CHAINFLIP_API_KEY + + const step = tradeQuote.steps[0] + const sellChainflipChainKey = `${step.sellAsset.symbol.toLowerCase()}.${ + chainIdToChainflipNetwork[step.sellAsset.chainId] + }` + const buyChainflipChainKey = `${step.buyAsset.symbol.toLowerCase()}.${ + chainIdToChainflipNetwork[step.buyAsset.chainId] + }` + + // Subtract the BaaS fee to end up at the final displayed commissionBps + let serviceCommission = parseInt(tradeQuote.affiliateBps) - CHAINFLIP_BAAS_COMMISSION + if (serviceCommission < 0) serviceCommission = 0 + + const maybeSwapResponse = await chainflipService.get( + `${brokerUrl}/swap` + + `?apiKey=${apiKey}` + + `&sourceAsset=${sellChainflipChainKey}` + + `&destinationAsset=${buyChainflipChainKey}` + + `&destinationAddress=${tradeQuote.receiveAddress}` + + `&boostFee=10` + + // TODO: Calculate minprice based on tradeQuote.slippageTolerancePercentageDecimal, step.sellAmountIncludingProtocolFeesCryptoBaseUnit, step.buyAmountAfterFeesCryptoBaseUnit + // `&minimumPrice=` + + // `&refundAddress=${from}` + + // `&retryDurationInBlocks=10` + + `&commissionBps=${serviceCommission}`, + + // TODO: Below is the reference code of Chainflip to calculate the minPrice parameter + // const tolerance = new BigNumber(params.slippageTolerancePercent); + // const estimatedPrice = new BigNumber(quote.estimatedPrice); + // minPrice = estimatedPrice + // .times(new BigNumber(100).minus(tolerance).dividedBy(100)) + // .toFixed(assetConstants[destAsset].decimals); + + // TODO: For DCA swaps we need to add the numberOfChunks/chunkIntervalBlocks parameters + ) + + if (maybeSwapResponse.isErr()) { + const error = maybeSwapResponse.unwrapErr() + const cause = error.cause as AxiosError + throw Error(cause.response!.data.detail) + } + + const { data: swapResponse } = maybeSwapResponse.unwrap() + + if (!swapResponse.id) throw Error('missing swap ID') + + tradeQuoteMetadata.set(tradeQuote.id, swapResponse) + + const depositAddress = swapResponse.address! + const { assetReference } = fromAssetId(step.sellAsset.assetId) + const isTokenSend = isToken(step.sellAsset.assetId) + + const adapter = assertGetEvmChainAdapter(step.sellAsset.chainId) + + const getFeeDataInput: GetFeeDataInput = { + to: depositAddress, + value: step.sellAmountIncludingProtocolFeesCryptoBaseUnit, + chainSpecific: { + from, + contractAddress: isTokenSend ? assetReference : undefined, + data: undefined, + }, + sendMax: false, + } + const feeData = await adapter.getFeeData(getFeeDataInput) + const fees = feeData[FeeDataKey.Average] + + if (!isExecutableTradeStep(step)) throw Error('Unable to execute trade step') + + const unsignedTxInput = await adapter.buildSendApiTransaction({ + to: depositAddress, + from, + value: step.sellAmountIncludingProtocolFeesCryptoBaseUnit, + accountNumber: step.accountNumber, + chainSpecific: { + gasLimit: fees.chainSpecific.gasLimit, + contractAddress: isTokenSend ? assetReference : undefined, + ...(supportsEIP1559 + ? { + maxFeePerGas: fees.chainSpecific.maxFeePerGas!, + maxPriorityFeePerGas: fees.chainSpecific.maxPriorityFeePerGas!, + } + : { + gasPrice: fees.chainSpecific.gasPrice, + }), + }, + }) + + return { + chainId: Number(fromChainId(chainId).chainReference), + data: unsignedTxInput.data, + to: unsignedTxInput.to, + from, + value: unsignedTxInput.value, + gasLimit: unsignedTxInput.gasLimit, + maxFeePerGas: unsignedTxInput.maxFeePerGas, + maxPriorityFeePerGas: unsignedTxInput.maxPriorityFeePerGas, + gasPrice: unsignedTxInput.gasPrice, + } + }, getUnsignedUtxoTransaction, - checkTradeStatus: ( - _input, - ): Promise<{ + checkTradeStatus: async ({ + config, + quoteId, + }): Promise<{ status: TxStatus buyTxHash: string | undefined message: string | [string, InterpolationOptions] | undefined }> => { - // TODO(gomes): implement me + const swap = tradeQuoteMetadata.get(quoteId) + if (!swap) throw Error(`missing trade quote metadata for quoteId ${quoteId}`) + // Note, the swapId isn't the quoteId - we set the swapId at pre-execution time, when getting the receive addy and instantiating a flip swap + const swapId = swap.id + + const brokerUrl = config.REACT_APP_CHAINFLIP_API_URL + const apiKey = config.REACT_APP_CHAINFLIP_API_KEY + + const maybeStatusResponse = await chainflipService.get( + `${brokerUrl}/status-by-id?apiKey=${apiKey}&swapId=${swapId}`, + ) + + if (maybeStatusResponse.isErr()) { + return { + buyTxHash: undefined, + status: TxStatus.Unknown, + message: undefined, + } + } + + const { data: statusResponse } = maybeStatusResponse.unwrap() + const { + status: { state, swapEgress }, + } = statusResponse + + // Assume any state that isn't completed is pending. + // Going forward, we will want to add granular status polling similar to what we do for THOR. + if (state !== 'completed' || !swapEgress?.transactionReference) { + return { + buyTxHash: undefined, + status: TxStatus.Pending, + message: undefined, + } + } + return { - // @ts-ignore TODO(gomes): implement me - buyTxHash: undefined, - status: TxStatus.Unknown, + buyTxHash: swapEgress.transactionReference, + status: TxStatus.Confirmed, message: undefined, } }, diff --git a/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusEgress.ts b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusEgress.ts new file mode 100644 index 00000000000..0bc245ee830 --- /dev/null +++ b/packages/swapper/src/swappers/ChainflipSwapper/models/ChainflipBaasStatusEgress.ts @@ -0,0 +1,149 @@ +// @ts-nocheck +/* tslint:disable */ +/* eslint-disable */ +/** + * Chainflip Broker as a Service + * Run your own Chainflip Broker without any hassle. + * + * The version of the OpenAPI document: v1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +import type { ChainflipBaasStatusFailure } from './ChainflipBaasStatusFailure'; +import { + ChainflipBaasStatusFailureFromJSON, + ChainflipBaasStatusFailureFromJSONTyped, + ChainflipBaasStatusFailureToJSON, +} from './ChainflipBaasStatusFailure'; + +/** + * + * @export + * @interface ChainflipBaasStatusEgress + */ +export interface ChainflipBaasStatusEgress { + /** + * + * @type {string} + * @memberof ChainflipBaasStatusEgress + */ + readonly amountNative?: string; + /** + * + * @type {number} + * @memberof ChainflipBaasStatusEgress + */ + readonly amount?: number; + /** + * + * @type {number} + * @memberof ChainflipBaasStatusEgress + */ + readonly scheduledAt?: number | null; + /** + * + * @type {Date} + * @memberof ChainflipBaasStatusEgress + */ + readonly scheduledAtDate?: Date | null; + /** + * + * @type {string} + * @memberof ChainflipBaasStatusEgress + */ + readonly scheduledBlockIndex?: string | null; + /** + * + * @type {string} + * @memberof ChainflipBaasStatusEgress + */ + readonly transactionReference?: string | null; + /** + * + * @type {number} + * @memberof ChainflipBaasStatusEgress + */ + readonly witnessedAt?: number | null; + /** + * + * @type {string} + * @memberof ChainflipBaasStatusEgress + */ + readonly witnessedBlockIndex?: string | null; + /** + * + * @type {ChainflipBaasStatusFailure} + * @memberof ChainflipBaasStatusEgress + */ + failure?: ChainflipBaasStatusFailure; + /** + * + * @type {number} + * @memberof ChainflipBaasStatusEgress + */ + readonly failedAt?: number | null; + /** + * + * @type {Date} + * @memberof ChainflipBaasStatusEgress + */ + readonly failedAtDate?: Date | null; + /** + * + * @type {string} + * @memberof ChainflipBaasStatusEgress + */ + readonly failedBlockIndex?: string | null; +} + +/** + * Check if a given object implements the ChainflipBaasStatusEgress interface. + */ +export function instanceOfChainflipBaasStatusEgress(value: object): boolean { + let isInstance = true; + + return isInstance; +} + +export function ChainflipBaasStatusEgressFromJSON(json: any): ChainflipBaasStatusEgress { + return ChainflipBaasStatusEgressFromJSONTyped(json, false); +} + +export function ChainflipBaasStatusEgressFromJSONTyped(json: any, ignoreDiscriminator: boolean): ChainflipBaasStatusEgress { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'amountNative': !exists(json, 'amountNative') ? undefined : json['amountNative'], + 'amount': !exists(json, 'amount') ? undefined : json['amount'], + 'scheduledAt': !exists(json, 'scheduledAt') ? undefined : json['scheduledAt'], + 'scheduledAtDate': !exists(json, 'scheduledAtDate') ? undefined : (json['scheduledAtDate'] === null ? null : new Date(json['scheduledAtDate'])), + 'scheduledBlockIndex': !exists(json, 'scheduledBlockIndex') ? undefined : json['scheduledBlockIndex'], + 'transactionReference': !exists(json, 'transactionReference') ? undefined : json['transactionReference'], + 'witnessedAt': !exists(json, 'witnessedAt') ? undefined : json['witnessedAt'], + 'witnessedBlockIndex': !exists(json, 'witnessedBlockIndex') ? undefined : json['witnessedBlockIndex'], + 'failure': !exists(json, 'failure') ? undefined : ChainflipBaasStatusFailureFromJSON(json['failure']), + 'failedAt': !exists(json, 'failedAt') ? undefined : json['failedAt'], + 'failedAtDate': !exists(json, 'failedAtDate') ? undefined : (json['failedAtDate'] === null ? null : new Date(json['failedAtDate'])), + 'failedBlockIndex': !exists(json, 'failedBlockIndex') ? undefined : json['failedBlockIndex'], + }; +} + +export function ChainflipBaasStatusEgressToJSON(value?: ChainflipBaasStatusEgress | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'failure': ChainflipBaasStatusFailureToJSON(value.failure), + }; +} diff --git a/packages/swapper/src/swappers/ChainflipSwapper/utils/chainflipService.ts b/packages/swapper/src/swappers/ChainflipSwapper/utils/chainflipService.ts index 5b087a231c7..b31c2a1e40f 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/utils/chainflipService.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/utils/chainflipService.ts @@ -1,7 +1,7 @@ import { SwapperName } from '../../../types' import { createCache, makeSwapperAxiosServiceMonadic } from '../../../utils' -const maxAge = 60 * 60 * 1000 // 1 hour cache for assets +const maxAge = 15 * 1000 // 15 seconds ttl for all except cached to get fresh status updates const cachedUrls = ['/assets/'] const axiosConfig = { From 267eb4f3184d87f0fdaaff0a9221357a5caf572f Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Mon, 4 Nov 2024 15:17:34 +0900 Subject: [PATCH 077/127] feat: flip polling and messaging --- .../swappers/ChainflipSwapper/endpoints.ts | 22 ++++++---------- .../src/swappers/ChainflipSwapper/types.ts | 10 +++++++ .../utils/getLatestChainflipStatusMessage.ts | 26 +++++++++++++++++++ .../ChainflipSwapper/utils/getUtxoTxFees.ts | 4 +-- 4 files changed, 46 insertions(+), 16 deletions(-) create mode 100644 packages/swapper/src/swappers/ChainflipSwapper/types.ts create mode 100644 packages/swapper/src/swappers/ChainflipSwapper/utils/getLatestChainflipStatusMessage.ts diff --git a/packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts b/packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts index 8700f072bbc..4fd14854d56 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts @@ -9,19 +9,12 @@ import type { InterpolationOptions } from 'node-polyglot' import type { EvmTransactionRequest, GetUnsignedEvmTransactionArgs, SwapperApi } from '../../types' import { isExecutableTradeQuote, isExecutableTradeStep, isToken } from '../../utils' import { CHAINFLIP_BAAS_COMMISSION, chainIdToChainflipNetwork } from './constants' -import type { ChainflipBaasStatusEgress } from './models/ChainflipBaasStatusEgress' import type { ChainflipBaasSwapDepositAddress } from './models/ChainflipBaasSwapDepositAddress' import { getTradeQuote, getTradeRate } from './swapperApi/getTradeQuote' import { getUnsignedUtxoTransaction } from './swapperApi/getUnsignedUtxoTransaction' +import type { ChainFlipStatus } from './types' import { chainflipService } from './utils/chainflipService' - -// Non-exhaustive -type ChainFlipStatus = { - status: { - state: 'waiting' | 'receiving' | 'swapping' | 'sending' | 'sent' | 'completed' | 'failed' - swapEgress?: ChainflipBaasStatusEgress - } -} +import { getLatestChainflipStatusMessage } from './utils/getLatestChainflipStatusMessage' // Persists the ID so we can look it up later when checking the status const tradeQuoteMetadata: Map = new Map() @@ -172,19 +165,20 @@ export const chainflipApi: SwapperApi = { const { data: statusResponse } = maybeStatusResponse.unwrap() const { - status: { state, swapEgress }, + status: { swapEgress }, } = statusResponse - // Assume any state that isn't completed is pending. - // Going forward, we will want to add granular status polling similar to what we do for THOR. - if (state !== 'completed' || !swapEgress?.transactionReference) { + // Assume no outbound Tx is a pending Tx + if (!swapEgress?.transactionReference) { return { buyTxHash: undefined, status: TxStatus.Pending, - message: undefined, + message: getLatestChainflipStatusMessage(statusResponse), } } + // Assume as soon as we have an outbound Tx, the swap is complete. + // Chainflip waits for 3 confirmations to assume complete (vs. 1 for us), which is turbo long. return { buyTxHash: swapEgress.transactionReference, status: TxStatus.Confirmed, diff --git a/packages/swapper/src/swappers/ChainflipSwapper/types.ts b/packages/swapper/src/swappers/ChainflipSwapper/types.ts new file mode 100644 index 00000000000..44411595176 --- /dev/null +++ b/packages/swapper/src/swappers/ChainflipSwapper/types.ts @@ -0,0 +1,10 @@ +import type { ChainflipBaasStatusEgress } from './models/ChainflipBaasStatusEgress' + +// Non-exhaustive +export type ChainFlipStatus = { + status: { + // TODO(gomes): Status polling a la THOR + state: 'waiting' | 'receiving' | 'swapping' | 'sending' | 'sent' | 'completed' | 'failed' + swapEgress?: ChainflipBaasStatusEgress + } +} diff --git a/packages/swapper/src/swappers/ChainflipSwapper/utils/getLatestChainflipStatusMessage.ts b/packages/swapper/src/swappers/ChainflipSwapper/utils/getLatestChainflipStatusMessage.ts new file mode 100644 index 00000000000..dc8b685e2c3 --- /dev/null +++ b/packages/swapper/src/swappers/ChainflipSwapper/utils/getLatestChainflipStatusMessage.ts @@ -0,0 +1,26 @@ +import type { ChainFlipStatus } from '../types' + +export const getLatestChainflipStatusMessage = (status: ChainFlipStatus): string => { + const { state, swapEgress } = status.status + + switch (state) { + case 'waiting': + return 'Waiting for deposit...' + case 'receiving': + return 'Deposit detected, waiting for confirmation...' + case 'swapping': + return 'Processing swap...' + case 'sent': + return 'Transaction sent, waiting for confirmation...' + case 'sending': + return swapEgress?.transactionReference + ? 'Outbound transaction initiated...' + : 'Preparing outbound transaction...' + case 'completed': + return 'Swap complete' + case 'failed': + return 'Swap failed' + default: + return 'Unknown status' + } +} diff --git a/packages/swapper/src/swappers/ChainflipSwapper/utils/getUtxoTxFees.ts b/packages/swapper/src/swappers/ChainflipSwapper/utils/getUtxoTxFees.ts index a89fafb66e0..7b2650431d3 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/utils/getUtxoTxFees.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/utils/getUtxoTxFees.ts @@ -13,9 +13,9 @@ export const getUtxoTxFees = async ({ sellAdapter, publicKey, }: GetUtxoTxFeesInput): Promise => { - // TODO: Get Chainflip BTC vault address const getFeeDataInput: GetFeeDataInput = { - to: '', + // One of many vault addresses - just used as a placeholder for the sake of loosely estimating fees - we *need* a *to* address for simulation or this will throw + to: 'bc1pfh5x55a3v92klcrdy5yv6yrt7fzr0g929klkdtapp3njfyu4qsyq8qacyf', value: sellAmountCryptoBaseUnit, chainSpecific: { pubkey: publicKey }, } From ae0dd3509598d47e9fb91351a33c87297e9fae71 Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Mon, 4 Nov 2024 23:33:22 +0900 Subject: [PATCH 078/127] feat: improve btc things --- .../swappers/ChainflipSwapper/endpoints.ts | 78 +++++++++++- .../swapperApi/getTradeQuote.ts | 16 +-- .../swapperApi/getUnsignedEvmTransaction.ts | 119 ------------------ .../ChainflipSwapper/utils/getUtxoTxFees.ts | 12 +- 4 files changed, 93 insertions(+), 132 deletions(-) delete mode 100644 packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts diff --git a/packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts b/packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts index 4fd14854d56..924365a2b3e 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts @@ -1,17 +1,23 @@ import { fromAssetId, fromChainId } from '@shapeshiftoss/caip' import type { GetFeeDataInput } from '@shapeshiftoss/chain-adapters' import { FeeDataKey } from '@shapeshiftoss/chain-adapters' -import type { EvmChainId } from '@shapeshiftoss/types' +import type { BTCSignTx } from '@shapeshiftoss/hdwallet-core' +import type { EvmChainId, KnownChainIds } from '@shapeshiftoss/types' import { TxStatus } from '@shapeshiftoss/unchained-client' import type { AxiosError } from 'axios' import type { InterpolationOptions } from 'node-polyglot' -import type { EvmTransactionRequest, GetUnsignedEvmTransactionArgs, SwapperApi } from '../../types' +import type { + EvmTransactionRequest, + GetUnsignedEvmTransactionArgs, + GetUnsignedUtxoTransactionArgs, + SwapperApi, + UtxoFeeData, +} from '../../types' import { isExecutableTradeQuote, isExecutableTradeStep, isToken } from '../../utils' import { CHAINFLIP_BAAS_COMMISSION, chainIdToChainflipNetwork } from './constants' import type { ChainflipBaasSwapDepositAddress } from './models/ChainflipBaasSwapDepositAddress' import { getTradeQuote, getTradeRate } from './swapperApi/getTradeQuote' -import { getUnsignedUtxoTransaction } from './swapperApi/getUnsignedUtxoTransaction' import type { ChainFlipStatus } from './types' import { chainflipService } from './utils/chainflipService' import { getLatestChainflipStatusMessage } from './utils/getLatestChainflipStatusMessage' @@ -134,7 +140,71 @@ export const chainflipApi: SwapperApi = { gasPrice: unsignedTxInput.gasPrice, } }, - getUnsignedUtxoTransaction, + getUnsignedUtxoTransaction: async ({ + tradeQuote, + xpub, + accountType, + assertGetUtxoChainAdapter, + config, + }: GetUnsignedUtxoTransactionArgs): Promise => { + if (!isExecutableTradeQuote(tradeQuote)) throw Error('Unable to execute trade') + + const brokerUrl = config.REACT_APP_CHAINFLIP_API_URL + const apiKey = config.REACT_APP_CHAINFLIP_API_KEY + + const step = tradeQuote.steps[0] + + if (!isExecutableTradeStep(step)) throw Error('Unable to execute step') + + const sellChainflipChainKey = `${step.sellAsset.symbol.toLowerCase()}.${ + chainIdToChainflipNetwork[step.sellAsset.chainId as KnownChainIds] + }` + const buyChainflipChainKey = `${step.buyAsset.symbol.toLowerCase()}.${ + chainIdToChainflipNetwork[step.buyAsset.chainId as KnownChainIds] + }` + + // Subtract the BaaS fee to end up at the final displayed commissionBps + let serviceCommission = parseInt(tradeQuote.affiliateBps) - CHAINFLIP_BAAS_COMMISSION + if (serviceCommission < 0) serviceCommission = 0 + + const maybeSwapResponse = await chainflipService.get( + `${brokerUrl}/swap` + + `?apiKey=${apiKey}` + + `&sourceAsset=${sellChainflipChainKey}` + + `&destinationAsset=${buyChainflipChainKey}` + + `&destinationAddress=${tradeQuote.receiveAddress}` + + `&boostFee=10` + + // TODO: Calculate minprice based on tradeQuote.slippageTolerancePercentageDecimal, step.sellAmountIncludingProtocolFeesCryptoBaseUnit + // `&minimumPrice=` + + // `&refundAddress=${from}` + + // `&retryDurationInBlocks=10` + + `&commissionBps=${serviceCommission}`, + + // TODO: For DCA swaps we need to add the numberOfChunks/chunkIntervalBlocks parameters + ) + + if (maybeSwapResponse.isErr()) { + const error = maybeSwapResponse.unwrapErr() + const cause = error.cause as AxiosError + throw Error(cause.response!.data.detail) + } + + const { data: swapResponse } = maybeSwapResponse.unwrap() + + const depositAddress = swapResponse.address! + + return assertGetUtxoChainAdapter(step.sellAsset.chainId).buildSendApiTransaction({ + value: step.sellAmountIncludingProtocolFeesCryptoBaseUnit, + xpub: xpub!, + to: depositAddress, + accountNumber: step.accountNumber, + skipToAddressValidation: true, + chainSpecific: { + accountType, + satoshiPerByte: (step.feeData.chainSpecific as UtxoFeeData).satsPerByte, + }, + }) + }, checkTradeStatus: async ({ config, quoteId, diff --git a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts index 1f25c186ef3..0c2447af6c9 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts @@ -141,34 +141,35 @@ const _getTradeQuote = async ( const { data: quoteResponse } = maybeQuoteResponse.unwrap() - const getNetworkFeeCryptoBaseUnit = async () => { + const getFeeData = async () => { const { chainNamespace } = fromAssetId(sellAsset.assetId) switch (chainNamespace) { case CHAIN_NAMESPACE.Evm: { const sellAdapter = deps.assertGetEvmChainAdapter(sellAsset.chainId) // TODO(gomes): double check dis correct - return await getEvmTxFees({ + const networkFeeCryptoBaseUnit = await getEvmTxFees({ adapter: sellAdapter, supportsEIP1559: (input as GetEvmTradeQuoteInput).supportsEIP1559, sendAsset: sellChainflipChainKey, }) + return { networkFeeCryptoBaseUnit } } case CHAIN_NAMESPACE.Utxo: { const sellAdapter = deps.assertGetUtxoChainAdapter(sellAsset.chainId) const publicKey = (input as GetUtxoTradeQuoteInput).xpub! - // TODO(gomes): double check dis correct - return await getUtxoTxFees({ + const feeData = await getUtxoTxFees({ sellAmountCryptoBaseUnit: sellAmount, sellAdapter, publicKey, }) + + return feeData } // TODO(gomes): Solana support case CHAIN_NAMESPACE.Solana: - return undefined default: throw new Error('Unsupported chainNamespace') } @@ -234,6 +235,7 @@ const _getTradeQuote = async ( for (const singleQuoteResponse of quoteResponse) { const isStreaming = singleQuoteResponse.type === CHAINFLIP_DCA_QUOTE + const feeData = await getFeeData() if (isStreaming && !deps.config.REACT_APP_FEATURE_CHAINFLIP_DCA) { // DCA currently disabled - Streaming swap logic is very much tied to THOR currently and will deserve its own PR to generalize @@ -264,8 +266,8 @@ const _getTradeQuote = async ( sellAmountIncludingProtocolFeesCryptoBaseUnit: singleQuoteResponse.boostQuote.ingressAmountNative!, feeData: { - networkFeeCryptoBaseUnit: await getNetworkFeeCryptoBaseUnit(), protocolFees: getProtocolFees(singleQuoteResponse.boostQuote), + ...feeData, }, rate: boostRate, source: getSwapSource(singleQuoteResponse.type, true), @@ -303,8 +305,8 @@ const _getTradeQuote = async ( buyAmountAfterFeesCryptoBaseUnit: singleQuoteResponse.egressAmountNative!, sellAmountIncludingProtocolFeesCryptoBaseUnit: singleQuoteResponse.ingressAmountNative!, feeData: { - networkFeeCryptoBaseUnit: await getNetworkFeeCryptoBaseUnit(), protocolFees: getProtocolFees(singleQuoteResponse), + ...feeData, }, rate, source: getSwapSource(singleQuoteResponse.type, false), diff --git a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts deleted file mode 100644 index d314bf48d7c..00000000000 --- a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedEvmTransaction.ts +++ /dev/null @@ -1,119 +0,0 @@ -import { fromAssetId, fromChainId } from '@shapeshiftoss/caip' -import { FeeDataKey, type GetFeeDataInput } from '@shapeshiftoss/chain-adapters' -import type { EvmChainId } from '@shapeshiftoss/types' -import type { AxiosError } from 'axios' - -import type { EvmTransactionRequest, GetUnsignedEvmTransactionArgs } from '../../../types' -import { isExecutableTradeQuote, isExecutableTradeStep, isToken } from '../../../utils' -import { CHAINFLIP_BAAS_COMMISSION, chainIdToChainflipNetwork } from '../constants' -import type { ChainflipBaasSwapDepositAddress } from '../models' -import { chainflipService } from '../utils/chainflipService' - -export const getUnsignedEvmTransaction = async ({ - chainId, - from, - tradeQuote, - assertGetEvmChainAdapter, - config, - supportsEIP1559, -}: GetUnsignedEvmTransactionArgs): Promise => { - if (!isExecutableTradeQuote(tradeQuote)) throw Error('Unable to execute trade') - - const brokerUrl = config.REACT_APP_CHAINFLIP_API_URL - const apiKey = config.REACT_APP_CHAINFLIP_API_KEY - - const step = tradeQuote.steps[0] - const sellChainflipChainKey = `${step.sellAsset.symbol.toLowerCase()}.${ - chainIdToChainflipNetwork[step.sellAsset.chainId] - }` - const buyChainflipChainKey = `${step.buyAsset.symbol.toLowerCase()}.${ - chainIdToChainflipNetwork[step.buyAsset.chainId] - }` - - // Subtract the BaaS fee to end up at the final displayed commissionBps - let serviceCommission = parseInt(tradeQuote.affiliateBps) - CHAINFLIP_BAAS_COMMISSION - if (serviceCommission < 0) serviceCommission = 0 - - const maybeSwapResponse = await chainflipService.get( - `${brokerUrl}/swap` + - `?apiKey=${apiKey}` + - `&sourceAsset=${sellChainflipChainKey}` + - `&destinationAsset=${buyChainflipChainKey}` + - `&destinationAddress=${tradeQuote.receiveAddress}` + - `&boostFee=10` + - // TODO: Calculate minprice based on tradeQuote.slippageTolerancePercentageDecimal, step.sellAmountIncludingProtocolFeesCryptoBaseUnit, step.buyAmountAfterFeesCryptoBaseUnit - // `&minimumPrice=` + - // `&refundAddress=${from}` + - // `&retryDurationInBlocks=10` + - `&commissionBps=${serviceCommission}`, - - // TODO: Below is the reference code of Chainflip to calculate the minPrice parameter - // const tolerance = new BigNumber(params.slippageTolerancePercent); - // const estimatedPrice = new BigNumber(quote.estimatedPrice); - // minPrice = estimatedPrice - // .times(new BigNumber(100).minus(tolerance).dividedBy(100)) - // .toFixed(assetConstants[destAsset].decimals); - - // TODO: For DCA swaps we need to add the numberOfChunks/chunkIntervalBlocks parameters - ) - - if (maybeSwapResponse.isErr()) { - const error = maybeSwapResponse.unwrapErr() - const cause = error.cause as AxiosError - throw Error(cause.response!.data.detail) - } - - const { data: swapResponse } = maybeSwapResponse.unwrap() - - const depositAddress = swapResponse.address! - const { assetReference } = fromAssetId(step.sellAsset.assetId) - const isTokenSend = isToken(step.sellAsset.assetId) - - const adapter = assertGetEvmChainAdapter(step.sellAsset.chainId) - - const getFeeDataInput: GetFeeDataInput = { - to: depositAddress, - value: step.sellAmountIncludingProtocolFeesCryptoBaseUnit, - chainSpecific: { - from, - contractAddress: isTokenSend ? assetReference : undefined, - data: undefined, - }, - sendMax: false, - } - const feeData = await adapter.getFeeData(getFeeDataInput) - const fees = feeData[FeeDataKey.Average] - - if (!isExecutableTradeStep(step)) throw Error('Unable to execute trade step') - - const unsignedTxInput = await adapter.buildSendApiTransaction({ - to: depositAddress, - from, - value: step.sellAmountIncludingProtocolFeesCryptoBaseUnit, - accountNumber: step.accountNumber, - chainSpecific: { - gasLimit: fees.chainSpecific.gasLimit, - contractAddress: isTokenSend ? assetReference : undefined, - ...(supportsEIP1559 - ? { - maxFeePerGas: fees.chainSpecific.maxFeePerGas!, - maxPriorityFeePerGas: fees.chainSpecific.maxPriorityFeePerGas!, - } - : { - gasPrice: fees.chainSpecific.gasPrice, - }), - }, - }) - - return { - chainId: Number(fromChainId(chainId).chainReference), - data: unsignedTxInput.data, - to: unsignedTxInput.to, - from, - value: unsignedTxInput.value, - gasLimit: unsignedTxInput.gasLimit, - maxFeePerGas: unsignedTxInput.maxFeePerGas, - maxPriorityFeePerGas: unsignedTxInput.maxPriorityFeePerGas, - gasPrice: unsignedTxInput.gasPrice, - } -} diff --git a/packages/swapper/src/swappers/ChainflipSwapper/utils/getUtxoTxFees.ts b/packages/swapper/src/swappers/ChainflipSwapper/utils/getUtxoTxFees.ts index 7b2650431d3..e269a1fb7de 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/utils/getUtxoTxFees.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/utils/getUtxoTxFees.ts @@ -2,6 +2,8 @@ import type { GetFeeDataInput, UtxoChainAdapter } from '@shapeshiftoss/chain-ada import type { UtxoChainId } from '@shapeshiftoss/types' import { bn } from '@shapeshiftoss/utils' +import type { QuoteFeeData } from '../../../types' + type GetUtxoTxFeesInput = { sellAmountCryptoBaseUnit: string sellAdapter: UtxoChainAdapter @@ -12,7 +14,7 @@ export const getUtxoTxFees = async ({ sellAmountCryptoBaseUnit, sellAdapter, publicKey, -}: GetUtxoTxFeesInput): Promise => { +}: GetUtxoTxFeesInput): Promise> => { const getFeeDataInput: GetFeeDataInput = { // One of many vault addresses - just used as a placeholder for the sake of loosely estimating fees - we *need* a *to* address for simulation or this will throw to: 'bc1pfh5x55a3v92klcrdy5yv6yrt7fzr0g929klkdtapp3njfyu4qsyq8qacyf', @@ -24,5 +26,11 @@ export const getUtxoTxFees = async ({ const feeData = feeDataOptions['fast'] - return bn(feeData.txFee).dp(0).toString() + return { + networkFeeCryptoBaseUnit: feeData.txFee, + chainSpecific: { + satsPerByte: feeData.chainSpecific.satoshiPerByte, + byteCount: bn(feeData.txFee).dividedBy(feeData.chainSpecific.satoshiPerByte).dp(0).toString(), + }, + } } From b28bb4e40520b630ac8fc2f544945b9ed6062bc9 Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Tue, 12 Nov 2024 07:36:45 +0700 Subject: [PATCH 079/127] chore: trigger CI From 757f42e1ee4c79916f9a5f571d472f63f11cdc7f Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Tue, 12 Nov 2024 07:49:50 +0700 Subject: [PATCH 080/127] feat: swapper re-enable solana --- src/components/TradeAssetSearch/TradeAssetSearch.tsx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/components/TradeAssetSearch/TradeAssetSearch.tsx b/src/components/TradeAssetSearch/TradeAssetSearch.tsx index f0c5e84e868..59cbe358353 100644 --- a/src/components/TradeAssetSearch/TradeAssetSearch.tsx +++ b/src/components/TradeAssetSearch/TradeAssetSearch.tsx @@ -162,12 +162,10 @@ export const TradeAssetSearch: FC = ({ return walletConnectedChainIds })() - const sortedChainIds = sortChainIdsByDisplayName(unsortedChainIds).filter(chainId => - isSwapper ? chainId !== KnownChainIds.SolanaMainnet : true, - ) + const sortedChainIds = sortChainIdsByDisplayName(unsortedChainIds) return ['All', ...sortedChainIds] - }, [allowWalletUnsupportedAssets, hasWallet, walletConnectedChainIds, isSwapper]) + }, [allowWalletUnsupportedAssets, hasWallet, walletConnectedChainIds]) const quickAccessAssetButtons = useMemo(() => { if (isPopularAssetIdsLoading) { From d2afed0333897c10ef4b1e1572e6b1a3f2f3609b Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Tue, 12 Nov 2024 08:15:28 +0700 Subject: [PATCH 081/127] feat: solana fee estimates --- .../swapperApi/getTradeQuote.ts | 25 ++++++++++++++++--- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts index 0c2447af6c9..6dffd3f74a5 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts @@ -1,5 +1,7 @@ import type { AssetId } from '@shapeshiftoss/caip' -import { CHAIN_NAMESPACE, fromAssetId } from '@shapeshiftoss/caip' +import { CHAIN_NAMESPACE, fromAssetId, solAssetId } from '@shapeshiftoss/caip' +import type { GetFeeDataInput } from '@shapeshiftoss/chain-adapters' +import type { KnownChainIds } from '@shapeshiftoss/types' import type { Result } from '@sniptt/monads' import { Err, Ok } from '@sniptt/monads' import type { AxiosError } from 'axios' @@ -147,7 +149,6 @@ const _getTradeQuote = async ( switch (chainNamespace) { case CHAIN_NAMESPACE.Evm: { const sellAdapter = deps.assertGetEvmChainAdapter(sellAsset.chainId) - // TODO(gomes): double check dis correct const networkFeeCryptoBaseUnit = await getEvmTxFees({ adapter: sellAdapter, supportsEIP1559: (input as GetEvmTradeQuoteInput).supportsEIP1559, @@ -168,8 +169,24 @@ const _getTradeQuote = async ( return feeData } - // TODO(gomes): Solana support - case CHAIN_NAMESPACE.Solana: + case CHAIN_NAMESPACE.Solana: { + const sellAdapter = deps.assertGetEvmChainAdapter(sellAsset.chainId) + const getFeeDataInput: GetFeeDataInput = { + // Simulates a self-send, since we don't know the to just yet at this stage + to: input.sendAddress!, + value: sellAmount, + chainSpecific: { + from: input.sendAddress!, + tokenId: + sellAsset.assetId === solAssetId + ? undefined + : fromAssetId(sellAsset.assetId).assetReference, + }, + } + const { fast } = await sellAdapter.getFeeData(getFeeDataInput) + return { networkFeeCryptoBaseUnit: fast.txFee } + } + default: throw new Error('Unsupported chainNamespace') } From 86e7a0b2854e6dc1fb7739b0998c4e689404a0ee Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Tue, 12 Nov 2024 08:24:51 +0700 Subject: [PATCH 082/127] fix: derp --- .../swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts | 2 +- packages/swapper/src/types.ts | 8 +++++++- src/state/apis/swapper/swapperApi.ts | 2 ++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts index 6dffd3f74a5..a8435a9565d 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts @@ -170,7 +170,7 @@ const _getTradeQuote = async ( } case CHAIN_NAMESPACE.Solana: { - const sellAdapter = deps.assertGetEvmChainAdapter(sellAsset.chainId) + const sellAdapter = deps.assertGetSolanaChainAdapter(sellAsset.chainId) const getFeeDataInput: GetFeeDataInput = { // Simulates a self-send, since we don't know the to just yet at this stage to: input.sendAddress!, diff --git a/packages/swapper/src/types.ts b/packages/swapper/src/types.ts index 771bb333ecb..19644feb872 100644 --- a/packages/swapper/src/types.ts +++ b/packages/swapper/src/types.ts @@ -6,6 +6,7 @@ import type { EvmChainAdapter, UtxoChainAdapter, } from '@shapeshiftoss/chain-adapters' +import type { ChainAdapter as SolanaChainAdapter } from '@shapeshiftoss/chain-adapters/dist/solana/SolanaChainAdapter' import type { BTCSignTx, HDWallet } from '@shapeshiftoss/hdwallet-core' import type { AccountMetadata, @@ -220,13 +221,18 @@ export type CosmosSdkSwapperDeps = { assertGetCosmosSdkChainAdapter: (chainId: ChainId) => CosmosSdkChainAdapter } +export type SolanaSwapperDeps = { + assertGetSolanaChainAdapter: (chainId: ChainId) => SolanaChainAdapter +} + export type SwapperDeps = { assetsById: AssetsByIdPartial config: SwapperConfig assertGetChainAdapter: (chainId: ChainId) => ChainAdapter } & EvmSwapperDeps & UtxoSwapperDeps & - CosmosSdkSwapperDeps + CosmosSdkSwapperDeps & + SolanaSwapperDeps export type TradeQuoteStep = { buyAmountBeforeFeesCryptoBaseUnit: string diff --git a/src/state/apis/swapper/swapperApi.ts b/src/state/apis/swapper/swapperApi.ts index 417720dd6ed..b19ec9952a7 100644 --- a/src/state/apis/swapper/swapperApi.ts +++ b/src/state/apis/swapper/swapperApi.ts @@ -19,6 +19,7 @@ import { fetchIsSmartContractAddressQuery } from 'hooks/useIsSmartContractAddres import { assertGetChainAdapter } from 'lib/utils' import { assertGetCosmosSdkChainAdapter } from 'lib/utils/cosmosSdk' import { assertGetEvmChainAdapter } from 'lib/utils/evm' +import { assertGetSolanaChainAdapter } from 'lib/utils/solana' import { thorchainBlockTimeMs } from 'lib/utils/thorchain/constants' import { assertGetUtxoChainAdapter } from 'lib/utils/utxo' import { getInputOutputRatioFromQuote } from 'state/apis/swapper/helpers/getInputOutputRatioFromQuote' @@ -73,6 +74,7 @@ export const swapperApi = createApi({ assertGetEvmChainAdapter, assertGetUtxoChainAdapter, assertGetCosmosSdkChainAdapter, + assertGetSolanaChainAdapter, fetchIsSmartContractAddressQuery, config: getConfig(), } From 7f3fafd8fd15e11fcf818be1ec9ad7ba94329e76 Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Tue, 12 Nov 2024 08:57:52 +0700 Subject: [PATCH 083/127] feat: solana progression --- packages/swapper/src/types.ts | 20 ++++++- src/lib/tradeExecution.ts | 53 +++++++++++++++++++ .../Stake/Bridge/hooks/useRfoxBridge.ts | 2 + 3 files changed, 74 insertions(+), 1 deletion(-) diff --git a/packages/swapper/src/types.ts b/packages/swapper/src/types.ts index 19644feb872..19d3995cf05 100644 --- a/packages/swapper/src/types.ts +++ b/packages/swapper/src/types.ts @@ -7,7 +7,7 @@ import type { UtxoChainAdapter, } from '@shapeshiftoss/chain-adapters' import type { ChainAdapter as SolanaChainAdapter } from '@shapeshiftoss/chain-adapters/dist/solana/SolanaChainAdapter' -import type { BTCSignTx, HDWallet } from '@shapeshiftoss/hdwallet-core' +import type { BTCSignTx, HDWallet, SolanaSignTx } from '@shapeshiftoss/hdwallet-core' import type { AccountMetadata, Asset, @@ -342,7 +342,12 @@ export type CosmosSdkTransactionExecutionProps = { signAndBroadcastTransaction: (transactionRequest: StdSignDoc) => Promise } +export type SolanaTransactionExecutionProps = { + signAndBroadcastTransaction: (transactionRequest: SolanaSignTx) => Promise +} + type EvmAccountMetadata = { from: string } +type SolanaAccountMetadata = { from: string } type UtxoAccountMetadata = { xpub: string; accountType: UtxoAccountType } type CosmosSdkAccountMetadata = { from: string } @@ -361,6 +366,10 @@ export type GetUnsignedEvmTransactionArgs = CommonGetUnsignedTransactionArgs & supportsEIP1559: boolean } +export type GetUnsignedSolanaTransactionArgs = CommonGetUnsignedTransactionArgs & + SolanaAccountMetadata & + SolanaSwapperDeps + export type GetUnsignedEvmMessageArgs = CommonGetUnsignedTransactionArgs & EvmAccountMetadata & Omit @@ -440,6 +449,10 @@ export type Swapper = { txToSign: StdSignDoc, callbacks: CosmosSdkTransactionExecutionProps, ) => Promise + executeSolanaTransaction?: ( + txToSign: SolanaSignTx, + callbacks: SolanaTransactionExecutionProps, + ) => Promise } export type SwapperApi = { @@ -460,6 +473,7 @@ export type SwapperApi = { getUnsignedCosmosSdkTransaction?: ( input: GetUnsignedCosmosSdkTransactionArgs, ) => Promise + getUnsignedSolanaTransaction?: (input: GetUnsignedSolanaTransactionArgs) => Promise } export type QuoteResult = Result & { @@ -493,6 +507,10 @@ export type CosmosSdkTransactionExecutionInput = CommonTradeExecutionInput & CosmosSdkTransactionExecutionProps & CosmosSdkAccountMetadata +export type SolanaTransactionExecutionInput = CommonTradeExecutionInput & + SolanaTransactionExecutionProps & + SolanaAccountMetadata + export enum TradeExecutionEvent { SellTxHash = 'sellTxHash', Status = 'status', diff --git a/src/lib/tradeExecution.ts b/src/lib/tradeExecution.ts index d5ca552ea41..71b591e87da 100644 --- a/src/lib/tradeExecution.ts +++ b/src/lib/tradeExecution.ts @@ -5,6 +5,7 @@ import type { EvmMessageExecutionInput, EvmTransactionExecutionInput, SellTxHashArgs, + SolanaTransactionExecutionInput, StatusArgs, Swapper, SwapperApi, @@ -28,6 +29,7 @@ import { store } from 'state/store' import { assertGetCosmosSdkChainAdapter } from './utils/cosmosSdk' import { assertGetEvmChainAdapter } from './utils/evm' +import { assertGetSolanaChainAdapter } from './utils/solana' import { assertGetUtxoChainAdapter } from './utils/utxo' export class TradeExecution { @@ -334,4 +336,55 @@ export class TradeExecution { buildSignBroadcast, ) } + + async execSolanaTransaction({ + swapperName, + tradeQuote, + stepIndex, + slippageTolerancePercentageDecimal, + from, + signAndBroadcastTransaction, + }: SolanaTransactionExecutionInput) { + const buildSignBroadcast = async ( + swapper: Swapper & SwapperApi, + { + tradeQuote, + chainId, + stepIndex, + slippageTolerancePercentageDecimal, + config, + }: CommonGetUnsignedTransactionArgs, + ) => { + if (!swapper.getUnsignedSolanaTransaction) { + throw Error('missing implementation for getUnsignedSolanaTransaction') + } + if (!swapper.executeSolanaTransaction) { + throw Error('missing implementation for executeSolanaTransaction') + } + + const unsignedTxResult = await swapper.getUnsignedSolanaTransaction({ + tradeQuote, + chainId, + stepIndex, + slippageTolerancePercentageDecimal, + from, + config, + assertGetSolanaChainAdapter, + }) + + return await swapper.executeSolanaTransaction(unsignedTxResult, { + signAndBroadcastTransaction, + }) + } + + return await this._execWalletAgnostic( + { + swapperName, + tradeQuote, + stepIndex, + slippageTolerancePercentageDecimal, + }, + buildSignBroadcast, + ) + } } diff --git a/src/pages/RFOX/components/Stake/Bridge/hooks/useRfoxBridge.ts b/src/pages/RFOX/components/Stake/Bridge/hooks/useRfoxBridge.ts index 233a40d09d2..9d34d29d2cd 100644 --- a/src/pages/RFOX/components/Stake/Bridge/hooks/useRfoxBridge.ts +++ b/src/pages/RFOX/components/Stake/Bridge/hooks/useRfoxBridge.ts @@ -28,6 +28,7 @@ import { buildAndBroadcast, createBuildCustomTxInput, } from 'lib/utils/evm' +import { assertGetSolanaChainAdapter } from 'lib/utils/solana' import { assertGetUtxoChainAdapter } from 'lib/utils/utxo' import { selectAccountNumberByAccountId, @@ -171,6 +172,7 @@ export const useRfoxBridge = ({ confirmedQuote }: UseRfoxBridgeProps): UseRfoxBr assertGetEvmChainAdapter, assertGetUtxoChainAdapter, assertGetCosmosSdkChainAdapter, + assertGetSolanaChainAdapter, getEthersV5Provider, fetchIsSmartContractAddressQuery, viemClientByChainId, From e165134a7704ac4ca39f33449aa413d9e794d875 Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Tue, 12 Nov 2024 09:06:17 +0700 Subject: [PATCH 084/127] feat: more sol progression --- .../hooks/useTradeExecution.tsx | 35 +++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/src/components/MultiHopTrade/components/MultiHopTradeConfirm/hooks/useTradeExecution.tsx b/src/components/MultiHopTrade/components/MultiHopTradeConfirm/hooks/useTradeExecution.tsx index afe98073a12..81028890d0b 100644 --- a/src/components/MultiHopTrade/components/MultiHopTradeConfirm/hooks/useTradeExecution.tsx +++ b/src/components/MultiHopTrade/components/MultiHopTradeConfirm/hooks/useTradeExecution.tsx @@ -2,7 +2,12 @@ import type { StdSignDoc } from '@keplr-wallet/types' import { bchAssetId, CHAIN_NAMESPACE, fromChainId } from '@shapeshiftoss/caip' import type { evm, SignTx, SignTypedDataInput } from '@shapeshiftoss/chain-adapters' import { toAddressNList } from '@shapeshiftoss/chain-adapters' -import type { BTCSignTx, ETHSignTypedData, ThorchainSignTx } from '@shapeshiftoss/hdwallet-core' +import type { + BTCSignTx, + ETHSignTypedData, + SolanaSignTx, + ThorchainSignTx, +} from '@shapeshiftoss/hdwallet-core' import { supportsETH } from '@shapeshiftoss/hdwallet-core' import type { EvmTransactionRequest, @@ -29,6 +34,7 @@ import { TradeExecution } from 'lib/tradeExecution' import { assertUnreachable } from 'lib/utils' import { assertGetCosmosSdkChainAdapter } from 'lib/utils/cosmosSdk' import { assertGetEvmChainAdapter, signAndBroadcast } from 'lib/utils/evm' +import { assertGetSolanaChainAdapter } from 'lib/utils/solana' import { assertGetUtxoChainAdapter } from 'lib/utils/utxo' import { selectThorVotingPower } from 'state/apis/snapshot/selectors' import { selectAssetById, selectPortfolioAccountMetadataByAccountId } from 'state/slices/selectors' @@ -407,8 +413,33 @@ export const useTradeExecution = ( cancelPollingRef.current = output?.cancelPolling return } - case CHAIN_NAMESPACE.Solana: + case CHAIN_NAMESPACE.Solana: { + const adapter = assertGetSolanaChainAdapter(stepSellAssetChainId) + const from = await adapter.getAddress({ accountNumber, wallet }) + const output = await execution.execSolanaTransaction({ + swapperName, + tradeQuote, + stepIndex: hopIndex, + slippageTolerancePercentageDecimal, + from, + signAndBroadcastTransaction: async (txToSign: SolanaSignTx) => { + const signedTx = await adapter.signTransaction({ + txToSign, + wallet, + }) + const output = await adapter.broadcastTransaction({ + senderAddress: from, + receiverAddress: tradeQuote.receiveAddress, + hex: signedTx, + }) + + trackMixpanelEventOnExecute() + return output + }, + }) + cancelPollingRef.current = output?.cancelPolling return + } default: assertUnreachable(stepSellAssetChainNamespace) } From 651649d615f039bb0f8867e4fc6ef33c581d5bc7 Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Tue, 12 Nov 2024 09:34:02 +0700 Subject: [PATCH 085/127] feat: solana build api Tx input and wire-up in flip --- .../src/solana/SolanaChainAdapter.ts | 19 +++- .../swappers/ChainflipSwapper/endpoints.ts | 91 ++++++++++++++++++- .../swapperApi/getUnsignedUtxoTransaction.ts | 75 --------------- 3 files changed, 104 insertions(+), 81 deletions(-) delete mode 100644 packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedUtxoTransaction.ts diff --git a/packages/chain-adapters/src/solana/SolanaChainAdapter.ts b/packages/chain-adapters/src/solana/SolanaChainAdapter.ts index 673daa500ab..279d456b9c0 100644 --- a/packages/chain-adapters/src/solana/SolanaChainAdapter.ts +++ b/packages/chain-adapters/src/solana/SolanaChainAdapter.ts @@ -36,6 +36,7 @@ import { ErrorHandler } from '../error/ErrorHandler' import type { Account, BroadcastTransactionInput, + BuildSendApiTxInput, BuildSendTxInput, FeeDataEstimate, GetAddressInput, @@ -203,14 +204,13 @@ export class ChainAdapter implements IChainAdapter } } - async buildSendTransaction(input: BuildSendTxInput): Promise<{ + async buildSendApiTransaction(input: BuildSendApiTxInput): Promise<{ txToSign: SignTx }> { try { - const { accountNumber, to, chainSpecific, value } = input + const { from, accountNumber, to, chainSpecific, value } = input const { instructions = [], tokenId } = chainSpecific - const from = await this.getAddress(input) const { blockhash } = await this.connection.getLatestBlockhash() const computeUnitLimit = chainSpecific.computeUnitLimit @@ -250,6 +250,19 @@ export class ChainAdapter implements IChainAdapter } } + async buildSendTransaction(input: BuildSendTxInput): Promise<{ + txToSign: SignTx + }> { + try { + const from = await this.getAddress(input) + const txToSign = await this.buildSendApiTransaction({ ...input, from }) + + return txToSign + } catch (err) { + return ErrorHandler(err) + } + } + async signTransaction(signTxInput: SignTxInput): Promise { try { const { txToSign, wallet } = signTxInput diff --git a/packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts b/packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts index 924365a2b3e..186ec7e0e5b 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts @@ -1,7 +1,7 @@ -import { fromAssetId, fromChainId } from '@shapeshiftoss/caip' -import type { GetFeeDataInput } from '@shapeshiftoss/chain-adapters' +import { fromAssetId, fromChainId, solAssetId } from '@shapeshiftoss/caip' +import type { BuildSendApiTxInput, GetFeeDataInput } from '@shapeshiftoss/chain-adapters' import { FeeDataKey } from '@shapeshiftoss/chain-adapters' -import type { BTCSignTx } from '@shapeshiftoss/hdwallet-core' +import type { BTCSignTx, SolanaSignTx } from '@shapeshiftoss/hdwallet-core' import type { EvmChainId, KnownChainIds } from '@shapeshiftoss/types' import { TxStatus } from '@shapeshiftoss/unchained-client' import type { AxiosError } from 'axios' @@ -10,6 +10,7 @@ import type { InterpolationOptions } from 'node-polyglot' import type { EvmTransactionRequest, GetUnsignedEvmTransactionArgs, + GetUnsignedSolanaTransactionArgs, GetUnsignedUtxoTransactionArgs, SwapperApi, UtxoFeeData, @@ -205,6 +206,90 @@ export const chainflipApi: SwapperApi = { }, }) }, + getUnsignedSolanaTransaction: async ({ + tradeQuote, + from, + assertGetSolanaChainAdapter, + config, + }: GetUnsignedSolanaTransactionArgs): Promise => { + if (!isExecutableTradeQuote(tradeQuote)) throw Error('Unable to execute trade') + + const brokerUrl = config.REACT_APP_CHAINFLIP_API_URL + const apiKey = config.REACT_APP_CHAINFLIP_API_KEY + + const step = tradeQuote.steps[0] + + if (!isExecutableTradeStep(step)) throw Error('Unable to execute step') + + const sellChainflipChainKey = `${step.sellAsset.symbol.toLowerCase()}.${ + chainIdToChainflipNetwork[step.sellAsset.chainId as KnownChainIds] + }` + const buyChainflipChainKey = `${step.buyAsset.symbol.toLowerCase()}.${ + chainIdToChainflipNetwork[step.buyAsset.chainId as KnownChainIds] + }` + + // Subtract the BaaS fee to end up at the final displayed commissionBps + let serviceCommission = parseInt(tradeQuote.affiliateBps) - CHAINFLIP_BAAS_COMMISSION + if (serviceCommission < 0) serviceCommission = 0 + + const maybeSwapResponse = await chainflipService.get( + `${brokerUrl}/swap` + + `?apiKey=${apiKey}` + + `&sourceAsset=${sellChainflipChainKey}` + + `&destinationAsset=${buyChainflipChainKey}` + + `&destinationAddress=${tradeQuote.receiveAddress}` + + `&boostFee=10` + + // TODO: Calculate minprice based on tradeQuote.slippageTolerancePercentageDecimal, step.sellAmountIncludingProtocolFeesCryptoBaseUnit + // `&minimumPrice=` + + // `&refundAddress=${from}` + + // `&retryDurationInBlocks=10` + + `&commissionBps=${serviceCommission}`, + + // TODO: For DCA swaps we need to add the numberOfChunks/chunkIntervalBlocks parameters + ) + + if (maybeSwapResponse.isErr()) { + const error = maybeSwapResponse.unwrapErr() + const cause = error.cause as AxiosError + throw Error(cause.response!.data.detail) + } + + const { data: swapResponse } = maybeSwapResponse.unwrap() + + const adapter = assertGetSolanaChainAdapter(step.sellAsset.chainId) + + const contractAddress = + step.sellAsset.assetId === solAssetId + ? undefined + : fromAssetId(step.sellAsset.assetId).assetReference + + const depositAddress = swapResponse.address! + + const getFeeDataInput: GetFeeDataInput = { + to: depositAddress, + value: step.sellAmountIncludingProtocolFeesCryptoBaseUnit, + chainSpecific: { + from, + tokenId: contractAddress, + }, + } + const { fast } = await adapter.getFeeData(getFeeDataInput) + + const buildSendTxInput: BuildSendApiTxInput = { + to: depositAddress, + from, + value: step.sellAmountIncludingProtocolFeesCryptoBaseUnit, + accountNumber: step.accountNumber, + chainSpecific: { + tokenId: contractAddress, + computeUnitLimit: fast.chainSpecific.computeUnits, + computeUnitPrice: fast.chainSpecific.priorityFee, + }, + } + + return (await adapter.buildSendApiTransaction(buildSendTxInput)).txToSign + }, + checkTradeStatus: async ({ config, quoteId, diff --git a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedUtxoTransaction.ts b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedUtxoTransaction.ts deleted file mode 100644 index 597b7be8377..00000000000 --- a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getUnsignedUtxoTransaction.ts +++ /dev/null @@ -1,75 +0,0 @@ -import type { BTCSignTx } from '@shapeshiftoss/hdwallet-core' -import type { KnownChainIds } from '@shapeshiftoss/types' -import type { AxiosError } from 'axios' - -import type { GetUnsignedUtxoTransactionArgs, UtxoFeeData } from '../../../types' -import { isExecutableTradeQuote, isExecutableTradeStep } from '../../../utils' -import { CHAINFLIP_BAAS_COMMISSION, chainIdToChainflipNetwork } from '../constants' -import type { ChainflipBaasSwapDepositAddress } from '../models' -import { chainflipService } from '../utils/chainflipService' - -export const getUnsignedUtxoTransaction = async ({ - tradeQuote, - xpub, - accountType, - assertGetUtxoChainAdapter, - config, -}: GetUnsignedUtxoTransactionArgs): Promise => { - if (!isExecutableTradeQuote(tradeQuote)) throw Error('Unable to execute trade') - - const brokerUrl = config.REACT_APP_CHAINFLIP_API_URL - const apiKey = config.REACT_APP_CHAINFLIP_API_KEY - - const step = tradeQuote.steps[0] - - if (!isExecutableTradeStep(step)) throw Error('Unable to execute step') - - const sellChainflipChainKey = `${step.sellAsset.symbol.toLowerCase()}.${ - chainIdToChainflipNetwork[step.sellAsset.chainId as KnownChainIds] - }` - const buyChainflipChainKey = `${step.buyAsset.symbol.toLowerCase()}.${ - chainIdToChainflipNetwork[step.buyAsset.chainId as KnownChainIds] - }` - - // Subtract the BaaS fee to end up at the final displayed commissionBps - let serviceCommission = parseInt(tradeQuote.affiliateBps) - CHAINFLIP_BAAS_COMMISSION - if (serviceCommission < 0) serviceCommission = 0 - - const maybeSwapResponse = await chainflipService.get( - `${brokerUrl}/swap` + - `?apiKey=${apiKey}` + - `&sourceAsset=${sellChainflipChainKey}` + - `&destinationAsset=${buyChainflipChainKey}` + - `&destinationAddress=${tradeQuote.receiveAddress}` + - `&boostFee=10` + - // TODO: Calculate minprice based on tradeQuote.slippageTolerancePercentageDecimal, step.sellAmountIncludingProtocolFeesCryptoBaseUnit - // `&minimumPrice=` + - // `&refundAddress=${from}` + - // `&retryDurationInBlocks=10` + - `&commissionBps=${serviceCommission}`, - - // TODO: For DCA swaps we need to add the numberOfChunks/chunkIntervalBlocks parameters - ) - - if (maybeSwapResponse.isErr()) { - const error = maybeSwapResponse.unwrapErr() - const cause = error.cause as AxiosError - throw Error(cause.response!.data.detail) - } - - const { data: swapResponse } = maybeSwapResponse.unwrap() - - const depositAddress = swapResponse.address! - - return assertGetUtxoChainAdapter(step.sellAsset.chainId).buildSendApiTransaction({ - value: step.sellAmountIncludingProtocolFeesCryptoBaseUnit, - xpub: xpub!, - to: depositAddress, - accountNumber: step.accountNumber, - skipToAddressValidation: true, - chainSpecific: { - accountType, - satoshiPerByte: (step.feeData.chainSpecific as UtxoFeeData).satsPerByte, - }, - }) -} From 9ea7c28e9a5f2a87aaf488ccce9ea3a04ee2ac01 Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Tue, 12 Nov 2024 09:38:47 +0700 Subject: [PATCH 086/127] feat: execute solana Tx --- .../src/swappers/ChainflipSwapper/ChainflipSwapper.ts | 3 ++- packages/swapper/src/utils.ts | 9 +++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/packages/swapper/src/swappers/ChainflipSwapper/ChainflipSwapper.ts b/packages/swapper/src/swappers/ChainflipSwapper/ChainflipSwapper.ts index d8a89152929..470e7df4260 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/ChainflipSwapper.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/ChainflipSwapper.ts @@ -3,12 +3,13 @@ import type { BTCSignTx } from '@shapeshiftoss/hdwallet-core' import type { Asset } from '@shapeshiftoss/types' import type { BuyAssetBySellIdInput, Swapper, UtxoTransactionExecutionProps } from '../../types' -import { executeEvmTransaction } from '../../utils' +import { executeEvmTransaction, executeSolanaTransaction } from '../../utils' import { CHAINFLIP_SUPPORTED_CHAIN_IDS } from './constants' import { isSupportedAssetId } from './utils/helpers' export const chainflipSwapper: Swapper = { executeEvmTransaction, + executeSolanaTransaction, executeUtxoTransaction: async ( txToSign: BTCSignTx, diff --git a/packages/swapper/src/utils.ts b/packages/swapper/src/utils.ts index d10856da7f9..5e39875e6a5 100644 --- a/packages/swapper/src/utils.ts +++ b/packages/swapper/src/utils.ts @@ -1,5 +1,6 @@ import { type AccountId, type AssetId, type ChainId, fromAssetId } from '@shapeshiftoss/caip' import type { EvmChainAdapter } from '@shapeshiftoss/chain-adapters' +import type { SolanaSignTx } from '@shapeshiftoss/hdwallet-core' import type { Asset } from '@shapeshiftoss/types' import { evm, TxStatus } from '@shapeshiftoss/unchained-client' import { bn, fromBaseUnit } from '@shapeshiftoss/utils' @@ -15,6 +16,7 @@ import type { EvmTransactionRequest, ExecutableTradeQuote, ExecutableTradeStep, + SolanaTransactionExecutionProps, SupportedTradeQuoteStepIndex, SwapErrorRight, SwapperName, @@ -169,6 +171,13 @@ export const executeEvmTransaction = ( return callbacks.signAndBroadcastTransaction(txToSign) } +export const executeSolanaTransaction = ( + txToSign: SolanaSignTx, + callbacks: SolanaTransactionExecutionProps, +) => { + return callbacks.signAndBroadcastTransaction(txToSign) +} + export const createDefaultStatusResponse = (buyTxHash?: string) => ({ status: TxStatus.Unknown, buyTxHash, From 59920828c342d2b340343a13282c691ecfeca33a Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Tue, 12 Nov 2024 10:03:35 +0700 Subject: [PATCH 087/127] fix: solana status --- packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts b/packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts index 186ec7e0e5b..9deb4ce364e 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts @@ -192,6 +192,8 @@ export const chainflipApi: SwapperApi = { const { data: swapResponse } = maybeSwapResponse.unwrap() + tradeQuoteMetadata.set(tradeQuote.id, swapResponse) + const depositAddress = swapResponse.address! return assertGetUtxoChainAdapter(step.sellAsset.chainId).buildSendApiTransaction({ @@ -256,6 +258,8 @@ export const chainflipApi: SwapperApi = { const { data: swapResponse } = maybeSwapResponse.unwrap() + tradeQuoteMetadata.set(tradeQuote.id, swapResponse) + const adapter = assertGetSolanaChainAdapter(step.sellAsset.chainId) const contractAddress = From 5da50735d021e0383b2168e0233bf60753116271 Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Tue, 12 Nov 2024 18:47:24 +0700 Subject: [PATCH 088/127] feat: slippidge protection --- .../swappers/ChainflipSwapper/endpoints.ts | 69 +++++++++++++------ .../swapperApi/getTradeQuote.ts | 12 ++-- .../ChainflipSwapper/utils/helpers.ts | 35 ++++++++++ 3 files changed, 90 insertions(+), 26 deletions(-) diff --git a/packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts b/packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts index 9deb4ce364e..4d1afb8c17b 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts @@ -22,6 +22,7 @@ import { getTradeQuote, getTradeRate } from './swapperApi/getTradeQuote' import type { ChainFlipStatus } from './types' import { chainflipService } from './utils/chainflipService' import { getLatestChainflipStatusMessage } from './utils/getLatestChainflipStatusMessage' +import { calculateChainflipMinPrice } from './utils/helpers' // Persists the ID so we can look it up later when checking the status const tradeQuoteMetadata: Map = new Map() @@ -50,6 +51,15 @@ export const chainflipApi: SwapperApi = { chainIdToChainflipNetwork[step.buyAsset.chainId] }` + const minimumPrice = calculateChainflipMinPrice({ + slippageTolerancePercentageDecimal: tradeQuote.slippageTolerancePercentageDecimal, + sellAsset: step.sellAsset, + buyAsset: step.buyAsset, + buyAmountAfterFeesCryptoBaseUnit: step.buyAmountAfterFeesCryptoBaseUnit, + sellAmountIncludingProtocolFeesCryptoBaseUnit: + step.sellAmountIncludingProtocolFeesCryptoBaseUnit, + }) + // Subtract the BaaS fee to end up at the final displayed commissionBps let serviceCommission = parseInt(tradeQuote.affiliateBps) - CHAINFLIP_BAAS_COMMISSION if (serviceCommission < 0) serviceCommission = 0 @@ -61,19 +71,11 @@ export const chainflipApi: SwapperApi = { `&destinationAsset=${buyChainflipChainKey}` + `&destinationAddress=${tradeQuote.receiveAddress}` + `&boostFee=10` + - // TODO: Calculate minprice based on tradeQuote.slippageTolerancePercentageDecimal, step.sellAmountIncludingProtocolFeesCryptoBaseUnit, step.buyAmountAfterFeesCryptoBaseUnit - // `&minimumPrice=` + - // `&refundAddress=${from}` + - // `&retryDurationInBlocks=10` + + `&minimumPrice=${minimumPrice}` + + `&refundAddress=${from}` + + `&retryDurationInBlocks=10` + `&commissionBps=${serviceCommission}`, - // TODO: Below is the reference code of Chainflip to calculate the minPrice parameter - // const tolerance = new BigNumber(params.slippageTolerancePercent); - // const estimatedPrice = new BigNumber(quote.estimatedPrice); - // minPrice = estimatedPrice - // .times(new BigNumber(100).minus(tolerance).dividedBy(100)) - // .toFixed(assetConstants[destAsset].decimals); - // TODO: For DCA swaps we need to add the numberOfChunks/chunkIntervalBlocks parameters ) @@ -168,6 +170,26 @@ export const chainflipApi: SwapperApi = { let serviceCommission = parseInt(tradeQuote.affiliateBps) - CHAINFLIP_BAAS_COMMISSION if (serviceCommission < 0) serviceCommission = 0 + const minimumPrice = calculateChainflipMinPrice({ + slippageTolerancePercentageDecimal: tradeQuote.slippageTolerancePercentageDecimal, + sellAsset: step.sellAsset, + buyAsset: step.buyAsset, + buyAmountAfterFeesCryptoBaseUnit: step.buyAmountAfterFeesCryptoBaseUnit, + sellAmountIncludingProtocolFeesCryptoBaseUnit: + step.sellAmountIncludingProtocolFeesCryptoBaseUnit, + }) + + const adapter = assertGetUtxoChainAdapter(step.sellAsset.chainId) + + const sendAddress = await adapter.getAddress({ + accountNumber: step.accountNumber, + // @ts-ignore this is a rare occurence of wallet not being passed but this being fine as we pass a pubKey instead + // types are stricter than they should for the sake of paranoia + wallet, + accountType, + pubKey: xpub, + }) + const maybeSwapResponse = await chainflipService.get( `${brokerUrl}/swap` + `?apiKey=${apiKey}` + @@ -175,10 +197,9 @@ export const chainflipApi: SwapperApi = { `&destinationAsset=${buyChainflipChainKey}` + `&destinationAddress=${tradeQuote.receiveAddress}` + `&boostFee=10` + - // TODO: Calculate minprice based on tradeQuote.slippageTolerancePercentageDecimal, step.sellAmountIncludingProtocolFeesCryptoBaseUnit - // `&minimumPrice=` + - // `&refundAddress=${from}` + - // `&retryDurationInBlocks=10` + + `&minimumPrice=${minimumPrice}` + + `&refundAddress=${sendAddress}` + + `&retryDurationInBlocks=10` + `&commissionBps=${serviceCommission}`, // TODO: For DCA swaps we need to add the numberOfChunks/chunkIntervalBlocks parameters @@ -196,7 +217,7 @@ export const chainflipApi: SwapperApi = { const depositAddress = swapResponse.address! - return assertGetUtxoChainAdapter(step.sellAsset.chainId).buildSendApiTransaction({ + return adapter.buildSendApiTransaction({ value: step.sellAmountIncludingProtocolFeesCryptoBaseUnit, xpub: xpub!, to: depositAddress, @@ -234,6 +255,15 @@ export const chainflipApi: SwapperApi = { let serviceCommission = parseInt(tradeQuote.affiliateBps) - CHAINFLIP_BAAS_COMMISSION if (serviceCommission < 0) serviceCommission = 0 + const minimumPrice = calculateChainflipMinPrice({ + slippageTolerancePercentageDecimal: tradeQuote.slippageTolerancePercentageDecimal, + sellAsset: step.sellAsset, + buyAsset: step.buyAsset, + buyAmountAfterFeesCryptoBaseUnit: step.buyAmountAfterFeesCryptoBaseUnit, + sellAmountIncludingProtocolFeesCryptoBaseUnit: + step.sellAmountIncludingProtocolFeesCryptoBaseUnit, + }) + const maybeSwapResponse = await chainflipService.get( `${brokerUrl}/swap` + `?apiKey=${apiKey}` + @@ -241,10 +271,9 @@ export const chainflipApi: SwapperApi = { `&destinationAsset=${buyChainflipChainKey}` + `&destinationAddress=${tradeQuote.receiveAddress}` + `&boostFee=10` + - // TODO: Calculate minprice based on tradeQuote.slippageTolerancePercentageDecimal, step.sellAmountIncludingProtocolFeesCryptoBaseUnit - // `&minimumPrice=` + - // `&refundAddress=${from}` + - // `&retryDurationInBlocks=10` + + `&minimumPrice=${minimumPrice}` + + `&refundAddress=${from}` + + `&retryDurationInBlocks=10` + `&commissionBps=${serviceCommission}`, // TODO: For DCA swaps we need to add the numberOfChunks/chunkIntervalBlocks parameters diff --git a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts index a8435a9565d..59e72f1d3c8 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts @@ -273,9 +273,9 @@ const _getTradeQuote = async ( potentialAffiliateBps: commissionBps, affiliateBps: commissionBps, isStreaming, - slippageTolerancePercentageDecimal: getDefaultSlippageDecimalPercentageForSwapper( - SwapperName.Chainflip, - ), + slippageTolerancePercentageDecimal: + input.slippageTolerancePercentageDecimal ?? + getDefaultSlippageDecimalPercentageForSwapper(SwapperName.Chainflip), steps: [ { buyAmountBeforeFeesCryptoBaseUnit: singleQuoteResponse.boostQuote.egressAmountNative!, @@ -313,9 +313,9 @@ const _getTradeQuote = async ( potentialAffiliateBps: commissionBps, affiliateBps: commissionBps, isStreaming, - slippageTolerancePercentageDecimal: getDefaultSlippageDecimalPercentageForSwapper( - SwapperName.Chainflip, - ), + slippageTolerancePercentageDecimal: + input.slippageTolerancePercentageDecimal ?? + getDefaultSlippageDecimalPercentageForSwapper(SwapperName.Chainflip), steps: [ { buyAmountBeforeFeesCryptoBaseUnit: singleQuoteResponse.egressAmountNative!, diff --git a/packages/swapper/src/swappers/ChainflipSwapper/utils/helpers.ts b/packages/swapper/src/swappers/ChainflipSwapper/utils/helpers.ts index 75f6dd12bfd..ffe5449a401 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/utils/helpers.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/utils/helpers.ts @@ -1,4 +1,6 @@ import { type AssetId, type ChainId } from '@shapeshiftoss/caip' +import type { Asset } from '@shapeshiftoss/types' +import { bn, bnOrZero, fromBaseUnit } from '@shapeshiftoss/utils' import type { ChainflipSupportedChainId } from '../constants' import { ChainflipSupportedAssetIdsByChainId, ChainflipSupportedChainIds } from '../constants' @@ -15,3 +17,36 @@ export const isSupportedAssetId = ( assetId, ) } + +export const calculateChainflipMinPrice = ({ + sellAmountIncludingProtocolFeesCryptoBaseUnit, + buyAmountAfterFeesCryptoBaseUnit, + slippageTolerancePercentageDecimal, + sellAsset, + buyAsset, +}: { + sellAmountIncludingProtocolFeesCryptoBaseUnit: string + buyAmountAfterFeesCryptoBaseUnit: string + slippageTolerancePercentageDecimal: string | undefined + sellAsset: Asset + buyAsset: Asset +}): string => { + const sellAmountCryptoPrecision = fromBaseUnit( + sellAmountIncludingProtocolFeesCryptoBaseUnit, + sellAsset.precision, + ) + + const buyAmountCryptoPrecision = fromBaseUnit( + buyAmountAfterFeesCryptoBaseUnit, + buyAsset.precision, + ) + + const estimatedPrice = bn(buyAmountCryptoPrecision).div(sellAmountCryptoPrecision) + + // This is called minimumPrice upstream but this really is a rate, let's not honour confusing terminology + const minimumRate = estimatedPrice + .times(bn(1).minus(bnOrZero(slippageTolerancePercentageDecimal))) + .toFixed(buyAsset.precision) + + return minimumRate +} From 90721262c906421f09e006e33ea98cba938be1a4 Mon Sep 17 00:00:00 2001 From: NeOMakinG <14963751+NeOMakinG@users.noreply.github.com> Date: Fri, 8 Nov 2024 15:10:18 +0100 Subject: [PATCH 089/127] feat: start jupiter swapper implementation --- .../src/solana/SolanaChainAdapter.ts | 10 ++- .../swappers/JupiterSwapper/JupiterSwapper.ts | 34 ++++++++ .../src/swappers/JupiterSwapper/endpoints.ts | 82 +++++++++++++++++++ .../src/swappers/JupiterSwapper/types.ts | 3 + .../JupiterSwapper/utils/constants.ts | 5 ++ .../filterBuyAssetsBySellAssetId.ts | 24 ++++++ packages/swapper/src/types.ts | 10 ++- packages/types/src/base.ts | 2 + 8 files changed, 168 insertions(+), 2 deletions(-) create mode 100644 packages/swapper/src/swappers/JupiterSwapper/JupiterSwapper.ts create mode 100644 packages/swapper/src/swappers/JupiterSwapper/endpoints.ts create mode 100644 packages/swapper/src/swappers/JupiterSwapper/types.ts create mode 100644 packages/swapper/src/swappers/JupiterSwapper/utils/constants.ts diff --git a/packages/chain-adapters/src/solana/SolanaChainAdapter.ts b/packages/chain-adapters/src/solana/SolanaChainAdapter.ts index 279d456b9c0..49190da3c72 100644 --- a/packages/chain-adapters/src/solana/SolanaChainAdapter.ts +++ b/packages/chain-adapters/src/solana/SolanaChainAdapter.ts @@ -8,7 +8,7 @@ import { } from '@shapeshiftoss/caip' import type { SolanaSignTx, SolanaTxInstruction } from '@shapeshiftoss/hdwallet-core' import { supportsSolana } from '@shapeshiftoss/hdwallet-core' -import type { BIP44Params } from '@shapeshiftoss/types' +import type { BIP44Params, SolanaChainId } from '@shapeshiftoss/types' import { KnownChainIds } from '@shapeshiftoss/types' import * as unchained from '@shapeshiftoss/unchained-client' import { BigNumber, bn } from '@shapeshiftoss/utils' @@ -57,6 +57,14 @@ import { toAddressNList, toRootDerivationPath } from '../utils' import { assertAddressNotSanctioned } from '../utils/validateAddress' import { microLamportsToLamports } from './utils' +export const solanaChainIds = [KnownChainIds.SolanaMainnet] as const + +export const isSolanaChainId = ( + maybeSolanaChainId: string | SolanaChainId, +): maybeSolanaChainId is SolanaChainId => { + return solanaChainIds.includes(maybeSolanaChainId as SolanaChainId) +} + // Maximum compute units allowed for a single solana transaction const MAX_COMPUTE_UNITS = 1400000 diff --git a/packages/swapper/src/swappers/JupiterSwapper/JupiterSwapper.ts b/packages/swapper/src/swappers/JupiterSwapper/JupiterSwapper.ts new file mode 100644 index 00000000000..8219f24812a --- /dev/null +++ b/packages/swapper/src/swappers/JupiterSwapper/JupiterSwapper.ts @@ -0,0 +1,34 @@ +import type { AssetId } from '@shapeshiftoss/caip' +import type { Asset } from '@shapeshiftoss/types' + +import { executeSolanaTransaction } from '../..' +import type { BuyAssetBySellIdInput, Swapper } from '../../types' +import { filterSameChainSolanaBuyAssetsBySellAssetId } from '../utils/filterBuyAssetsBySellAssetId/filterBuyAssetsBySellAssetId' +import type { JupiterSupportedChainId } from './types' +import { jupiterSupportedChainIds } from './utils/constants' + +export const jupiterSwapper: Swapper = { + executeSolanaTransaction, + + filterAssetIdsBySellable: (assets: Asset[]): Promise => { + return Promise.resolve( + assets + .filter(asset => { + const { chainId } = asset + return jupiterSupportedChainIds.includes(chainId as JupiterSupportedChainId) + }) + .map(asset => asset.assetId), + ) + }, + + filterBuyAssetsBySellAssetId: (input: BuyAssetBySellIdInput): Promise => { + return Promise.resolve( + filterSameChainSolanaBuyAssetsBySellAssetId(input) + .filter(asset => { + const { chainId } = asset + return jupiterSupportedChainIds.includes(chainId as JupiterSupportedChainId) + }) + .map(asset => asset.assetId), + ) + }, +} diff --git a/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts b/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts new file mode 100644 index 00000000000..8b9de6eb3e1 --- /dev/null +++ b/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts @@ -0,0 +1,82 @@ +import { fromChainId } from '@shapeshiftoss/caip' +import { TxStatus } from '@shapeshiftoss/unchained-client' +import type { Result } from '@sniptt/monads/build' +import type { InterpolationOptions } from 'node-polyglot' + +import type { + CommonTradeQuoteInput, + GetUnsignedSolanaTransactionArgs, + SolanaTransactionRequest, + TradeRate, +} from '../../types' +import { + type GetTradeQuoteInput, + type SwapErrorRight, + type SwapperApi, + type TradeQuote, +} from '../../types' +import { isExecutableTradeQuote } from '../../utils' + +export const jupiterApi: SwapperApi = { + getTradeQuote: ( + input: CommonTradeQuoteInput, + // { assertGetSolanaChainAdapter, assetsById, config }: SwapperDeps, + ): Promise> => { + return [] as unknown as Promise> + }, + getTradeRate: ( + input: GetTradeQuoteInput, + // { assertGetSolanaChainAdapter, assetsById, config }: SwapperDeps, + ): Promise> => { + return [] as unknown as Promise> + }, + getUnsignedSolanaTransaction: ({ + chainId, + from, + tradeQuote, + config, + }: GetUnsignedSolanaTransactionArgs): Promise => { + if (!isExecutableTradeQuote(tradeQuote)) throw new Error('Unable to execute trade') + + return { + to: '', + from, + value: '', + data: '', + chainId: Number(fromChainId(chainId).chainReference), + // Use the higher amount of the node or the API, as the node doesn't always provide enough gas padding for + // total gas used. + gasLimit: '1', + // @TODO: remove this + } as unknown as Promise + }, + + checkTradeStatus: (): Promise<{ + status: TxStatus + buyTxHash: string | undefined + message: string | [string, InterpolationOptions] | undefined + }> => { + try { + return { + buyTxHash: '', + status: TxStatus.Pending, + message: '', + } as unknown as Promise<{ + status: TxStatus + buyTxHash: string | undefined + message: string | [string, InterpolationOptions] | undefined + }> + } catch (e) { + console.error(e) + return { + buyTxHash: undefined, + status: TxStatus.Unknown, + message: undefined, + } as unknown as Promise<{ + status: TxStatus + buyTxHash: string | undefined + message: string | [string, InterpolationOptions] | undefined + }> + } + }, +} diff --git a/packages/swapper/src/swappers/JupiterSwapper/types.ts b/packages/swapper/src/swappers/JupiterSwapper/types.ts new file mode 100644 index 00000000000..bd5d56e59ec --- /dev/null +++ b/packages/swapper/src/swappers/JupiterSwapper/types.ts @@ -0,0 +1,3 @@ +import type { jupiterSupportedChainIds } from './utils/constants' + +export type JupiterSupportedChainId = (typeof jupiterSupportedChainIds)[number] diff --git a/packages/swapper/src/swappers/JupiterSwapper/utils/constants.ts b/packages/swapper/src/swappers/JupiterSwapper/utils/constants.ts new file mode 100644 index 00000000000..c63ed276ddb --- /dev/null +++ b/packages/swapper/src/swappers/JupiterSwapper/utils/constants.ts @@ -0,0 +1,5 @@ +import { KnownChainIds } from '@shapeshiftoss/types' + +export const ZRX_NATIVE_ASSET_ADDRESS = '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE' + +export const jupiterSupportedChainIds = [KnownChainIds.SolanaMainnet] as const diff --git a/packages/swapper/src/swappers/utils/filterBuyAssetsBySellAssetId/filterBuyAssetsBySellAssetId.ts b/packages/swapper/src/swappers/utils/filterBuyAssetsBySellAssetId/filterBuyAssetsBySellAssetId.ts index 816dc33954a..4c3572a2311 100644 --- a/packages/swapper/src/swappers/utils/filterBuyAssetsBySellAssetId/filterBuyAssetsBySellAssetId.ts +++ b/packages/swapper/src/swappers/utils/filterBuyAssetsBySellAssetId/filterBuyAssetsBySellAssetId.ts @@ -1,5 +1,6 @@ import { arbitrumNovaChainId, type ChainId } from '@shapeshiftoss/caip' import { isEvmChainId } from '@shapeshiftoss/chain-adapters' +import { isSolanaChainId } from '@shapeshiftoss/chain-adapters/src/solana/SolanaChainAdapter' import type { Asset } from '@shapeshiftoss/types' import type { BuyAssetBySellIdInput } from '../../../types' @@ -23,6 +24,21 @@ const _filterEvmBuyAssetsBySellAssetId = ( }) } +const _filterSolanaBuyAssetsBySellAssetId = ( + { assets, sellAsset }: BuyAssetBySellIdInput, + chainIdPredicate: ChainIdPredicate, +): Asset[] => { + // evm only + if (!isSolanaChainId(sellAsset.chainId)) return [] + + return assets.filter(buyAsset => { + // evm only AND chain id predicate with no arbitrum nova support for any swappers + return ( + isSolanaChainId(buyAsset.chainId) && chainIdPredicate(buyAsset.chainId, sellAsset.chainId) + ) + }) +} + export const filterSameChainEvmBuyAssetsBySellAssetId = (input: BuyAssetBySellIdInput): Asset[] => { const sameChainIdPredicate = (buyAssetChainId: ChainId, sellAssetChainId: ChainId): boolean => buyAssetChainId === sellAssetChainId @@ -36,3 +52,11 @@ export const filterCrossChainEvmBuyAssetsBySellAssetId = ( buyAssetChainId !== sellAssetChainId return _filterEvmBuyAssetsBySellAssetId(input, crossChainIdPredicate) } + +export const filterSameChainSolanaBuyAssetsBySellAssetId = ( + input: BuyAssetBySellIdInput, +): Asset[] => { + const sameChainIdPredicate = (buyAssetChainId: ChainId, sellAssetChainId: ChainId): boolean => + buyAssetChainId === sellAssetChainId + return _filterSolanaBuyAssetsBySellAssetId(input, sameChainIdPredicate) +} diff --git a/packages/swapper/src/types.ts b/packages/swapper/src/types.ts index 19d3995cf05..0e1642b042c 100644 --- a/packages/swapper/src/types.ts +++ b/packages/swapper/src/types.ts @@ -4,6 +4,7 @@ import type { ChainAdapter, CosmosSdkChainAdapter, EvmChainAdapter, + solana, UtxoChainAdapter, } from '@shapeshiftoss/chain-adapters' import type { ChainAdapter as SolanaChainAdapter } from '@shapeshiftoss/chain-adapters/dist/solana/SolanaChainAdapter' @@ -220,7 +221,6 @@ export type UtxoSwapperDeps = { assertGetUtxoChainAdapter: (chainId: ChainId) => export type CosmosSdkSwapperDeps = { assertGetCosmosSdkChainAdapter: (chainId: ChainId) => CosmosSdkChainAdapter } - export type SolanaSwapperDeps = { assertGetSolanaChainAdapter: (chainId: ChainId) => SolanaChainAdapter } @@ -415,6 +415,14 @@ export type CheckTradeStatusInput = { type TradeQuoteResult = Result export type TradeRateResult = Result +export type SolanaTransactionRequest = { + gasLimit: string + to: string + from: string + value: string + data: string +} + export type EvmTransactionRequest = { gasLimit: string to: string diff --git a/packages/types/src/base.ts b/packages/types/src/base.ts index 36994e9c872..0988b493035 100644 --- a/packages/types/src/base.ts +++ b/packages/types/src/base.ts @@ -48,6 +48,8 @@ export type UtxoChainId = | KnownChainIds.DogecoinMainnet | KnownChainIds.LitecoinMainnet +export type SolanaChainId = KnownChainIds.SolanaMainnet + export enum WithdrawType { DELAYED, INSTANT, From bd177c3be248127bb016d4f9888e687a1f97e335 Mon Sep 17 00:00:00 2001 From: NeOMakinG <14963751+NeOMakinG@users.noreply.github.com> Date: Tue, 12 Nov 2024 23:52:15 +0100 Subject: [PATCH 090/127] fix: continue --- .env.base | 3 + .../src/swappers/JupiterSwapper/endpoints.ts | 6 +- .../swapperApi/getTradeQuote.ts | 370 ++++++++++++++++++ .../JupiterSwapper/utils/constants.ts | 2 - .../swappers/JupiterSwapper/utils/helpers.ts | 50 +++ packages/swapper/src/types.ts | 1 - 6 files changed, 426 insertions(+), 6 deletions(-) create mode 100644 packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeQuote.ts create mode 100644 packages/swapper/src/swappers/JupiterSwapper/utils/helpers.ts diff --git a/.env.base b/.env.base index 59244a842a0..88bc07586b1 100644 --- a/.env.base +++ b/.env.base @@ -177,3 +177,6 @@ REACT_APP_ZRX_BASE_URL=https://api.proxy.shapeshift.com/api/v1/zrx/ # chainflip REACT_APP_CHAINFLIP_API_KEY=6ba154d4-e219-472a-9674-5fa5b1300ccf REACT_APP_CHAINFLIP_API_URL=https://chainflip-broker.io + +# jupiter +REACT_APP_JUPITER_API_URL=https://quote-api.jup.ag/v6 diff --git a/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts b/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts index 8b9de6eb3e1..bc7ad7edf05 100644 --- a/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts +++ b/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts @@ -1,4 +1,5 @@ import { fromChainId } from '@shapeshiftoss/caip' +import type { SolanaSignTx } from '@shapeshiftoss/hdwallet-core' import { TxStatus } from '@shapeshiftoss/unchained-client' import type { Result } from '@sniptt/monads/build' import type { InterpolationOptions } from 'node-polyglot' @@ -6,7 +7,6 @@ import type { InterpolationOptions } from 'node-polyglot' import type { CommonTradeQuoteInput, GetUnsignedSolanaTransactionArgs, - SolanaTransactionRequest, TradeRate, } from '../../types' import { @@ -35,7 +35,7 @@ export const jupiterApi: SwapperApi = { from, tradeQuote, config, - }: GetUnsignedSolanaTransactionArgs): Promise => { + }: GetUnsignedSolanaTransactionArgs): Promise => { if (!isExecutableTradeQuote(tradeQuote)) throw new Error('Unable to execute trade') return { @@ -48,7 +48,7 @@ export const jupiterApi: SwapperApi = { // total gas used. gasLimit: '1', // @TODO: remove this - } as unknown as Promise + } as unknown as Promise }, checkTradeStatus: (): Promise<{ diff --git a/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeQuote.ts b/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeQuote.ts new file mode 100644 index 00000000000..eb99c6d9c3a --- /dev/null +++ b/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeQuote.ts @@ -0,0 +1,370 @@ +import type { AssetId } from '@shapeshiftoss/caip' +import { CHAIN_NAMESPACE, fromAssetId, solAssetId } from '@shapeshiftoss/caip' +import type { GetFeeDataInput } from '@shapeshiftoss/chain-adapters' +import type { KnownChainIds } from '@shapeshiftoss/types' +import type { Result } from '@sniptt/monads' +import { Err, Ok } from '@sniptt/monads' +import type { AxiosError } from 'axios' +import { v4 as uuid } from 'uuid' + +import { getDefaultSlippageDecimalPercentageForSwapper } from '../../../constants' +import type { + CommonTradeQuoteInput, + GetTradeRateInput, + GetUtxoTradeQuoteInput, + SwapErrorRight, + SwapperDeps, + TradeQuote, + TradeRate, +} from '../../../types' +import { + type GetEvmTradeQuoteInput, + type ProtocolFee, + SwapperName, + TradeQuoteError, +} from '../../../types' +import { getRate, makeSwapErrorRight } from '../../../utils' +import { + CHAINFLIP_BAAS_COMMISSION, + CHAINFLIP_BOOST_SWAP_SOURCE, + CHAINFLIP_DCA_BOOST_SWAP_SOURCE, + CHAINFLIP_DCA_QUOTE, + CHAINFLIP_DCA_SWAP_SOURCE, + CHAINFLIP_REGULAR_QUOTE, + CHAINFLIP_SWAP_SOURCE, + chainIdToChainflipNetwork, + usdcAsset, +} from '../constants' +import type { ChainflipBaasQuoteQuote, ChainflipBaasQuoteQuoteFee } from '../models' +import { chainflipService } from '../utils/chainflipService' +import { getEvmTxFees } from '../utils/getEvmTxFees' +import { getUtxoTxFees } from '../utils/getUtxoTxFees' +import { isSupportedAssetId, isSupportedChainId } from '../utils/helpers' + +const _getTradeQuote = async ( + input: CommonTradeQuoteInput, + deps: SwapperDeps, +): Promise> => { + const { + sellAsset, + buyAsset, + accountNumber, + receiveAddress, + sellAmountIncludingProtocolFeesCryptoBaseUnit: sellAmount, + affiliateBps: commissionBps, + } = input + + if (!isSupportedChainId(sellAsset.chainId)) { + return Err( + makeSwapErrorRight({ + message: `unsupported chainId`, + code: TradeQuoteError.UnsupportedChain, + details: { chainId: sellAsset.chainId }, + }), + ) + } + + if (!isSupportedChainId(buyAsset.chainId)) { + return Err( + makeSwapErrorRight({ + message: `unsupported chainId`, + code: TradeQuoteError.UnsupportedChain, + details: { chainId: sellAsset.chainId }, + }), + ) + } + + if (!isSupportedAssetId(sellAsset.chainId, sellAsset.assetId)) { + return Err( + makeSwapErrorRight({ + message: `asset '${sellAsset.name}' on chainId '${sellAsset.chainId}' not supported`, + code: TradeQuoteError.UnsupportedTradePair, + details: { chainId: sellAsset.chainId, assetId: sellAsset.assetId }, + }), + ) + } + + if (!isSupportedAssetId(buyAsset.chainId, buyAsset.assetId)) { + return Err( + makeSwapErrorRight({ + message: `asset '${buyAsset.name}' on chainId '${buyAsset.chainId}' not supported`, + code: TradeQuoteError.UnsupportedTradePair, + details: { chainId: buyAsset.chainId, assetId: buyAsset.assetId }, + }), + ) + } + + const sellChainflipChainKey = `${sellAsset.symbol.toLowerCase()}.${ + chainIdToChainflipNetwork[sellAsset.chainId] + }` + const buyChainflipChainKey = `${buyAsset.symbol.toLowerCase()}.${ + chainIdToChainflipNetwork[buyAsset.chainId] + }` + + const brokerUrl = deps.config.REACT_APP_CHAINFLIP_API_URL + const apiKey = deps.config.REACT_APP_CHAINFLIP_API_KEY + + // Subtract the BaaS fee to end up at the final displayed commissionBps + let serviceCommission = parseInt(commissionBps) - CHAINFLIP_BAAS_COMMISSION + if (serviceCommission < 0) serviceCommission = 0 + + const maybeQuoteResponse = await chainflipService.get( + `${brokerUrl}/quotes-native` + + `?apiKey=${apiKey}` + + `&sourceAsset=${sellChainflipChainKey}` + + `&destinationAsset=${buyChainflipChainKey}` + + `&amount=${sellAmount}` + + `&commissionBps=${serviceCommission}`, + ) + + if (maybeQuoteResponse.isErr()) { + const error = maybeQuoteResponse.unwrapErr() + const cause = error.cause as AxiosError + + if ( + cause.message.includes('code 400') && + cause.response!.data.detail.includes('Amount outside asset bounds') + ) { + return Err( + makeSwapErrorRight({ + message: cause.response!.data.detail, + code: TradeQuoteError.SellAmountBelowMinimum, + }), + ) + } + + return Err( + makeSwapErrorRight({ + message: 'Quote request failed', + code: TradeQuoteError.NoRouteFound, + }), + ) + } + + const { data: quoteResponse } = maybeQuoteResponse.unwrap() + + const getFeeData = async () => { + const { chainNamespace } = fromAssetId(sellAsset.assetId) + + switch (chainNamespace) { + case CHAIN_NAMESPACE.Evm: { + const sellAdapter = deps.assertGetEvmChainAdapter(sellAsset.chainId) + const networkFeeCryptoBaseUnit = await getEvmTxFees({ + adapter: sellAdapter, + supportsEIP1559: (input as GetEvmTradeQuoteInput).supportsEIP1559, + sendAsset: sellChainflipChainKey, + }) + return { networkFeeCryptoBaseUnit } + } + + case CHAIN_NAMESPACE.Utxo: { + const sellAdapter = deps.assertGetUtxoChainAdapter(sellAsset.chainId) + const publicKey = (input as GetUtxoTradeQuoteInput).xpub! + const feeData = await getUtxoTxFees({ + sellAmountCryptoBaseUnit: sellAmount, + sellAdapter, + publicKey, + }) + + return feeData + } + + case CHAIN_NAMESPACE.Solana: { + const sellAdapter = deps.assertGetSolanaChainAdapter(sellAsset.chainId) + const getFeeDataInput: GetFeeDataInput = { + // Simulates a self-send, since we don't know the to just yet at this stage + to: input.sendAddress!, + value: sellAmount, + chainSpecific: { + from: input.sendAddress!, + tokenId: + sellAsset.assetId === solAssetId + ? undefined + : fromAssetId(sellAsset.assetId).assetReference, + }, + } + const { fast } = await sellAdapter.getFeeData(getFeeDataInput) + return { networkFeeCryptoBaseUnit: fast.txFee } + } + + default: + throw new Error('Unsupported chainNamespace') + } + } + + const getFeeAsset = (fee: ChainflipBaasQuoteQuoteFee) => { + if (fee.type === 'ingress' || fee.type === 'boost') return sellAsset + + if (fee.type === 'egress') return buyAsset + + if (fee.type === 'liquidity' && fee.asset === sellChainflipChainKey) return sellAsset + + if (fee.type === 'liquidity' && fee.asset === buyChainflipChainKey) return buyAsset + + if (fee.type === 'liquidity' && fee.asset === 'usdc.eth') return usdcAsset + + if (fee.type === 'network') return usdcAsset + } + + const getProtocolFees = (singleQuoteResponse: ChainflipBaasQuoteQuote) => { + const protocolFees: Record = {} + + for (const fee of singleQuoteResponse.includedFees!) { + if (fee.type === 'broker') continue + + const asset = getFeeAsset(fee)! + if (!(asset.assetId in protocolFees)) { + protocolFees[asset.assetId] = { + amountCryptoBaseUnit: '0', + requiresBalance: false, + asset, + } + } + + protocolFees[asset.assetId].amountCryptoBaseUnit = ( + BigInt(protocolFees[asset.assetId].amountCryptoBaseUnit) + BigInt(fee.amountNative!) + ).toString() + } + + return protocolFees + } + + const getQuoteRate = (sellAmountCryptoBaseUnit: string, buyAmountCryptoBaseUnit: string) => { + return getRate({ + sellAmountCryptoBaseUnit, + buyAmountCryptoBaseUnit, + sellAsset, + buyAsset, + }) + } + + const getSwapSource = (swapType: string | undefined, isBoosted: boolean) => { + return swapType === CHAINFLIP_REGULAR_QUOTE + ? isBoosted + ? CHAINFLIP_BOOST_SWAP_SOURCE + : CHAINFLIP_SWAP_SOURCE + : isBoosted + ? CHAINFLIP_DCA_BOOST_SWAP_SOURCE + : CHAINFLIP_DCA_SWAP_SOURCE + } + + const quotes: TradeQuote[] = [] + + for (const singleQuoteResponse of quoteResponse) { + const isStreaming = singleQuoteResponse.type === CHAINFLIP_DCA_QUOTE + const feeData = await getFeeData() + + if (isStreaming && !deps.config.REACT_APP_FEATURE_CHAINFLIP_DCA) { + // DCA currently disabled - Streaming swap logic is very much tied to THOR currently and will deserve its own PR to generalize + // Even if we manage to get DCA swaps to execute, we wouldn't manage to properly poll with current web THOR-centric arch + continue + } + + if (singleQuoteResponse.boostQuote) { + const boostRate = getQuoteRate( + singleQuoteResponse.boostQuote.ingressAmountNative!, + singleQuoteResponse.boostQuote.egressAmountNative!, + ) + + const boostTradeQuote: TradeQuote = { + id: uuid(), + rate: boostRate, + receiveAddress, + potentialAffiliateBps: commissionBps, + affiliateBps: commissionBps, + isStreaming, + slippageTolerancePercentageDecimal: + input.slippageTolerancePercentageDecimal ?? + getDefaultSlippageDecimalPercentageForSwapper(SwapperName.Chainflip), + steps: [ + { + buyAmountBeforeFeesCryptoBaseUnit: singleQuoteResponse.boostQuote.egressAmountNative!, + buyAmountAfterFeesCryptoBaseUnit: singleQuoteResponse.boostQuote.egressAmountNative!, + sellAmountIncludingProtocolFeesCryptoBaseUnit: + singleQuoteResponse.boostQuote.ingressAmountNative!, + feeData: { + protocolFees: getProtocolFees(singleQuoteResponse.boostQuote), + ...feeData, + }, + rate: boostRate, + source: getSwapSource(singleQuoteResponse.type, true), + buyAsset, + sellAsset, + accountNumber, + allowanceContract: '0x0', // Chainflip does not use contracts + estimatedExecutionTimeMs: + singleQuoteResponse.boostQuote.estimatedDurationSeconds! * 1000, + }, + ], + } + + quotes.push(boostTradeQuote) + } + + const rate = getQuoteRate( + singleQuoteResponse.ingressAmountNative!, + singleQuoteResponse.egressAmountNative!, + ) + + const tradeQuote: TradeQuote = { + id: uuid(), + rate, + receiveAddress, + potentialAffiliateBps: commissionBps, + affiliateBps: commissionBps, + isStreaming, + slippageTolerancePercentageDecimal: + input.slippageTolerancePercentageDecimal ?? + getDefaultSlippageDecimalPercentageForSwapper(SwapperName.Chainflip), + steps: [ + { + buyAmountBeforeFeesCryptoBaseUnit: singleQuoteResponse.egressAmountNative!, + buyAmountAfterFeesCryptoBaseUnit: singleQuoteResponse.egressAmountNative!, + sellAmountIncludingProtocolFeesCryptoBaseUnit: singleQuoteResponse.ingressAmountNative!, + feeData: { + protocolFees: getProtocolFees(singleQuoteResponse), + ...feeData, + }, + rate, + source: getSwapSource(singleQuoteResponse.type, false), + buyAsset, + sellAsset, + accountNumber, + allowanceContract: '0x0', // Chainflip does not use contracts - all Txs are sends + estimatedExecutionTimeMs: singleQuoteResponse.estimatedDurationSeconds! * 1000, + }, + ], + } + + quotes.push(tradeQuote) + } + + return Ok(quotes) +} + +export const getTradeRate = async ( + input: GetTradeRateInput, + deps: SwapperDeps, +): Promise> => { + const rates = await _getTradeQuote(input as unknown as CommonTradeQuoteInput, deps) + return rates as Result +} + +export const getTradeQuote = async ( + input: CommonTradeQuoteInput, + deps: SwapperDeps, +): Promise> => { + const { accountNumber } = input + + if (accountNumber === undefined) { + return Err( + makeSwapErrorRight({ + message: `accountNumber is required`, + code: TradeQuoteError.UnknownError, + }), + ) + } + + const quotes = await _getTradeQuote(input, deps) + return quotes +} diff --git a/packages/swapper/src/swappers/JupiterSwapper/utils/constants.ts b/packages/swapper/src/swappers/JupiterSwapper/utils/constants.ts index c63ed276ddb..8150c0032bb 100644 --- a/packages/swapper/src/swappers/JupiterSwapper/utils/constants.ts +++ b/packages/swapper/src/swappers/JupiterSwapper/utils/constants.ts @@ -1,5 +1,3 @@ import { KnownChainIds } from '@shapeshiftoss/types' -export const ZRX_NATIVE_ASSET_ADDRESS = '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE' - export const jupiterSupportedChainIds = [KnownChainIds.SolanaMainnet] as const diff --git a/packages/swapper/src/swappers/JupiterSwapper/utils/helpers.ts b/packages/swapper/src/swappers/JupiterSwapper/utils/helpers.ts new file mode 100644 index 00000000000..096d4bd7ae5 --- /dev/null +++ b/packages/swapper/src/swappers/JupiterSwapper/utils/helpers.ts @@ -0,0 +1,50 @@ +import { type AssetId, type ChainId } from '@shapeshiftoss/caip' +import type { Asset } from '@shapeshiftoss/types' +import { bn, bnOrZero, fromBaseUnit } from '@shapeshiftoss/utils' + +import type { JupiterSupportedChainId } from '../types' +import { jupiterSupportedChainIds } from './constants' + +export const isSupportedChainId = (chainId: ChainId): chainId is JupiterSupportedChainId => { + return jupiterSupportedChainIds.includes(chainId as JupiterSupportedChainId) +} + +export const isSupportedAssetId = ( + chainId: ChainId, + assetId: AssetId, +): chainId is JupiterSupportedChainId => { + return jupiterSupportedChainIds[chainId as JupiterSupportedChainId]!.includes(assetId) +} + +export const calculateChainflipMinPrice = ({ + sellAmountIncludingProtocolFeesCryptoBaseUnit, + buyAmountAfterFeesCryptoBaseUnit, + slippageTolerancePercentageDecimal, + sellAsset, + buyAsset, +}: { + sellAmountIncludingProtocolFeesCryptoBaseUnit: string + buyAmountAfterFeesCryptoBaseUnit: string + slippageTolerancePercentageDecimal: string | undefined + sellAsset: Asset + buyAsset: Asset +}): string => { + const sellAmountCryptoPrecision = fromBaseUnit( + sellAmountIncludingProtocolFeesCryptoBaseUnit, + sellAsset.precision, + ) + + const buyAmountCryptoPrecision = fromBaseUnit( + buyAmountAfterFeesCryptoBaseUnit, + buyAsset.precision, + ) + + const estimatedPrice = bn(buyAmountCryptoPrecision).div(sellAmountCryptoPrecision) + + // This is called minimumPrice upstream but this really is a rate, let's not honour confusing terminology + const minimumRate = estimatedPrice + .times(bn(1).minus(bnOrZero(slippageTolerancePercentageDecimal))) + .toFixed(buyAsset.precision) + + return minimumRate +} diff --git a/packages/swapper/src/types.ts b/packages/swapper/src/types.ts index 0e1642b042c..662b6a28f17 100644 --- a/packages/swapper/src/types.ts +++ b/packages/swapper/src/types.ts @@ -4,7 +4,6 @@ import type { ChainAdapter, CosmosSdkChainAdapter, EvmChainAdapter, - solana, UtxoChainAdapter, } from '@shapeshiftoss/chain-adapters' import type { ChainAdapter as SolanaChainAdapter } from '@shapeshiftoss/chain-adapters/dist/solana/SolanaChainAdapter' From bcce88c16a25e6f386fdc71f9242697106d86644 Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Wed, 13 Nov 2024 16:59:13 +0700 Subject: [PATCH 091/127] feat: add getChainFlipSwap --- .../swappers/ChainflipSwapper/endpoints.ts | 74 ++++++++----------- .../ChainflipSwapper/utils/helpers.ts | 46 ++++++++++++ 2 files changed, 77 insertions(+), 43 deletions(-) diff --git a/packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts b/packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts index 4d1afb8c17b..fbb397b9c1d 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts @@ -22,7 +22,7 @@ import { getTradeQuote, getTradeRate } from './swapperApi/getTradeQuote' import type { ChainFlipStatus } from './types' import { chainflipService } from './utils/chainflipService' import { getLatestChainflipStatusMessage } from './utils/getLatestChainflipStatusMessage' -import { calculateChainflipMinPrice } from './utils/helpers' +import { calculateChainflipMinPrice, getChainFlipSwap } from './utils/helpers' // Persists the ID so we can look it up later when checking the status const tradeQuoteMetadata: Map = new Map() @@ -64,20 +64,16 @@ export const chainflipApi: SwapperApi = { let serviceCommission = parseInt(tradeQuote.affiliateBps) - CHAINFLIP_BAAS_COMMISSION if (serviceCommission < 0) serviceCommission = 0 - const maybeSwapResponse = await chainflipService.get( - `${brokerUrl}/swap` + - `?apiKey=${apiKey}` + - `&sourceAsset=${sellChainflipChainKey}` + - `&destinationAsset=${buyChainflipChainKey}` + - `&destinationAddress=${tradeQuote.receiveAddress}` + - `&boostFee=10` + - `&minimumPrice=${minimumPrice}` + - `&refundAddress=${from}` + - `&retryDurationInBlocks=10` + - `&commissionBps=${serviceCommission}`, - - // TODO: For DCA swaps we need to add the numberOfChunks/chunkIntervalBlocks parameters - ) + const maybeSwapResponse = await getChainFlipSwap({ + brokerUrl, + apiKey, + sourceAsset: sellChainflipChainKey, + destinationAsset: buyChainflipChainKey, + destinationAddress: tradeQuote.receiveAddress, + minimumPrice, + refundAddress: from, + commissionBps: serviceCommission, + }) if (maybeSwapResponse.isErr()) { const error = maybeSwapResponse.unwrapErr() @@ -190,20 +186,16 @@ export const chainflipApi: SwapperApi = { pubKey: xpub, }) - const maybeSwapResponse = await chainflipService.get( - `${brokerUrl}/swap` + - `?apiKey=${apiKey}` + - `&sourceAsset=${sellChainflipChainKey}` + - `&destinationAsset=${buyChainflipChainKey}` + - `&destinationAddress=${tradeQuote.receiveAddress}` + - `&boostFee=10` + - `&minimumPrice=${minimumPrice}` + - `&refundAddress=${sendAddress}` + - `&retryDurationInBlocks=10` + - `&commissionBps=${serviceCommission}`, - - // TODO: For DCA swaps we need to add the numberOfChunks/chunkIntervalBlocks parameters - ) + const maybeSwapResponse = await getChainFlipSwap({ + brokerUrl, + apiKey, + sourceAsset: sellChainflipChainKey, + destinationAsset: buyChainflipChainKey, + destinationAddress: tradeQuote.receiveAddress, + minimumPrice, + refundAddress: sendAddress, + commissionBps: serviceCommission, + }) if (maybeSwapResponse.isErr()) { const error = maybeSwapResponse.unwrapErr() @@ -264,20 +256,16 @@ export const chainflipApi: SwapperApi = { step.sellAmountIncludingProtocolFeesCryptoBaseUnit, }) - const maybeSwapResponse = await chainflipService.get( - `${brokerUrl}/swap` + - `?apiKey=${apiKey}` + - `&sourceAsset=${sellChainflipChainKey}` + - `&destinationAsset=${buyChainflipChainKey}` + - `&destinationAddress=${tradeQuote.receiveAddress}` + - `&boostFee=10` + - `&minimumPrice=${minimumPrice}` + - `&refundAddress=${from}` + - `&retryDurationInBlocks=10` + - `&commissionBps=${serviceCommission}`, - - // TODO: For DCA swaps we need to add the numberOfChunks/chunkIntervalBlocks parameters - ) + const maybeSwapResponse = await getChainFlipSwap({ + brokerUrl, + apiKey, + sourceAsset: sellChainflipChainKey, + destinationAsset: buyChainflipChainKey, + destinationAddress: tradeQuote.receiveAddress, + minimumPrice, + refundAddress: from, + commissionBps: serviceCommission, + }) if (maybeSwapResponse.isErr()) { const error = maybeSwapResponse.unwrapErr() diff --git a/packages/swapper/src/swappers/ChainflipSwapper/utils/helpers.ts b/packages/swapper/src/swappers/ChainflipSwapper/utils/helpers.ts index ffe5449a401..af144263558 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/utils/helpers.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/utils/helpers.ts @@ -1,9 +1,27 @@ import { type AssetId, type ChainId } from '@shapeshiftoss/caip' import type { Asset } from '@shapeshiftoss/types' import { bn, bnOrZero, fromBaseUnit } from '@shapeshiftoss/utils' +import type { Result } from '@sniptt/monads' +import type { AxiosResponse } from 'axios' +import type { SwapErrorRight } from '../../../types' import type { ChainflipSupportedChainId } from '../constants' import { ChainflipSupportedAssetIdsByChainId, ChainflipSupportedChainIds } from '../constants' +import type { ChainflipBaasSwapDepositAddress } from '../models' +import { chainflipService } from './chainflipService' + +type GetChainFlipSwapArgs = { + brokerUrl: string + apiKey: string + sourceAsset: string + destinationAsset: string + destinationAddress: string + boostFee?: number + minimumPrice: string + refundAddress: string + retryDurationInBlocks?: number + commissionBps: number +} export const isSupportedChainId = (chainId: ChainId): chainId is ChainflipSupportedChainId => { return ChainflipSupportedChainIds.includes(chainId as ChainflipSupportedChainId) @@ -50,3 +68,31 @@ export const calculateChainflipMinPrice = ({ return minimumRate } + +export const getChainFlipSwap = ({ + brokerUrl, + apiKey, + sourceAsset, + destinationAsset, + destinationAddress, + boostFee = 10, + minimumPrice, + refundAddress, + retryDurationInBlocks = 10, + commissionBps, +}: GetChainFlipSwapArgs): Promise< + Result, SwapErrorRight> +> => + // TODO: For DCA swaps we need to add the numberOfChunks/chunkIntervalBlocks parameters + chainflipService.get( + `${brokerUrl}/swap` + + `?apiKey=${apiKey}` + + `&sourceAsset=${sourceAsset}` + + `&destinationAsset=${destinationAsset}` + + `&destinationAddress=${destinationAddress}` + + `&boostFee=${boostFee}` + + `&minimumPrice=${minimumPrice}` + + `&refundAddress=${refundAddress}` + + `&retryDurationInBlocks=${retryDurationInBlocks}` + + `&commissionBps=${commissionBps}`, + ) From d097f8c50149b80579acff700bc7f8e2afbb2a41 Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Wed, 13 Nov 2024 17:48:19 +0700 Subject: [PATCH 092/127] feat: getChainFlipIdFromAssetId --- .../swappers/ChainflipSwapper/constants.ts | 11 ++-- .../swappers/ChainflipSwapper/endpoints.ts | 65 +++++++++++-------- .../swapperApi/getTradeQuote.ts | 29 +++++---- .../src/swappers/ChainflipSwapper/types.ts | 7 ++ .../ChainflipSwapper/utils/helpers.ts | 61 ++++++++++++++++- 5 files changed, 124 insertions(+), 49 deletions(-) diff --git a/packages/swapper/src/swappers/ChainflipSwapper/constants.ts b/packages/swapper/src/swappers/ChainflipSwapper/constants.ts index 5ac6f5ced73..29dd686adc6 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/constants.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/constants.ts @@ -16,6 +16,7 @@ import { KnownChainIds } from '@shapeshiftoss/types' import type { SupportedChainIds, SwapSource } from '../../types' import { SwapperName } from '../../types' +import { ChainflipNetwork } from './types' export const CHAINFLIP_REGULAR_QUOTE = 'regular' export const CHAINFLIP_DCA_QUOTE = 'dca' @@ -37,11 +38,11 @@ export const ChainflipSupportedAssetIdsByChainId: Partial> = { - [KnownChainIds.EthereumMainnet]: 'eth', - [KnownChainIds.ArbitrumMainnet]: 'arb', - [KnownChainIds.BitcoinMainnet]: 'btc', - [KnownChainIds.SolanaMainnet]: 'sol', +export const chainIdToChainflipNetwork: Partial> = { + [KnownChainIds.EthereumMainnet]: ChainflipNetwork.Ethereum, + [KnownChainIds.ArbitrumMainnet]: ChainflipNetwork.Arbitrum, + [KnownChainIds.BitcoinMainnet]: ChainflipNetwork.Bitcoin, + [KnownChainIds.SolanaMainnet]: ChainflipNetwork.Solana, } export const CHAINFLIP_SUPPORTED_CHAIN_IDS: SupportedChainIds = { diff --git a/packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts b/packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts index fbb397b9c1d..25350ee68df 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts @@ -16,13 +16,17 @@ import type { UtxoFeeData, } from '../../types' import { isExecutableTradeQuote, isExecutableTradeStep, isToken } from '../../utils' -import { CHAINFLIP_BAAS_COMMISSION, chainIdToChainflipNetwork } from './constants' +import { CHAINFLIP_BAAS_COMMISSION } from './constants' import type { ChainflipBaasSwapDepositAddress } from './models/ChainflipBaasSwapDepositAddress' import { getTradeQuote, getTradeRate } from './swapperApi/getTradeQuote' import type { ChainFlipStatus } from './types' import { chainflipService } from './utils/chainflipService' import { getLatestChainflipStatusMessage } from './utils/getLatestChainflipStatusMessage' -import { calculateChainflipMinPrice, getChainFlipSwap } from './utils/helpers' +import { + calculateChainflipMinPrice, + getChainFlipIdFromAssetId, + getChainFlipSwap, +} from './utils/helpers' // Persists the ID so we can look it up later when checking the status const tradeQuoteMetadata: Map = new Map() @@ -44,12 +48,16 @@ export const chainflipApi: SwapperApi = { const apiKey = config.REACT_APP_CHAINFLIP_API_KEY const step = tradeQuote.steps[0] - const sellChainflipChainKey = `${step.sellAsset.symbol.toLowerCase()}.${ - chainIdToChainflipNetwork[step.sellAsset.chainId] - }` - const buyChainflipChainKey = `${step.buyAsset.symbol.toLowerCase()}.${ - chainIdToChainflipNetwork[step.buyAsset.chainId] - }` + + const isTokenSend = isToken(step.sellAsset.assetId) + const sourceAsset = await getChainFlipIdFromAssetId({ + assetId: step.sellAsset.assetId, + brokerUrl, + }) + const destinationAsset = await getChainFlipIdFromAssetId({ + assetId: step.buyAsset.assetId, + brokerUrl, + }) const minimumPrice = calculateChainflipMinPrice({ slippageTolerancePercentageDecimal: tradeQuote.slippageTolerancePercentageDecimal, @@ -67,8 +75,8 @@ export const chainflipApi: SwapperApi = { const maybeSwapResponse = await getChainFlipSwap({ brokerUrl, apiKey, - sourceAsset: sellChainflipChainKey, - destinationAsset: buyChainflipChainKey, + sourceAsset, + destinationAsset, destinationAddress: tradeQuote.receiveAddress, minimumPrice, refundAddress: from, @@ -89,7 +97,6 @@ export const chainflipApi: SwapperApi = { const depositAddress = swapResponse.address! const { assetReference } = fromAssetId(step.sellAsset.assetId) - const isTokenSend = isToken(step.sellAsset.assetId) const adapter = assertGetEvmChainAdapter(step.sellAsset.chainId) @@ -155,12 +162,14 @@ export const chainflipApi: SwapperApi = { if (!isExecutableTradeStep(step)) throw Error('Unable to execute step') - const sellChainflipChainKey = `${step.sellAsset.symbol.toLowerCase()}.${ - chainIdToChainflipNetwork[step.sellAsset.chainId as KnownChainIds] - }` - const buyChainflipChainKey = `${step.buyAsset.symbol.toLowerCase()}.${ - chainIdToChainflipNetwork[step.buyAsset.chainId as KnownChainIds] - }` + const sourceAsset = await getChainFlipIdFromAssetId({ + assetId: step.sellAsset.assetId, + brokerUrl, + }) + const destinationAsset = await getChainFlipIdFromAssetId({ + assetId: step.buyAsset.assetId, + brokerUrl, + }) // Subtract the BaaS fee to end up at the final displayed commissionBps let serviceCommission = parseInt(tradeQuote.affiliateBps) - CHAINFLIP_BAAS_COMMISSION @@ -189,8 +198,8 @@ export const chainflipApi: SwapperApi = { const maybeSwapResponse = await getChainFlipSwap({ brokerUrl, apiKey, - sourceAsset: sellChainflipChainKey, - destinationAsset: buyChainflipChainKey, + sourceAsset, + destinationAsset, destinationAddress: tradeQuote.receiveAddress, minimumPrice, refundAddress: sendAddress, @@ -236,12 +245,14 @@ export const chainflipApi: SwapperApi = { if (!isExecutableTradeStep(step)) throw Error('Unable to execute step') - const sellChainflipChainKey = `${step.sellAsset.symbol.toLowerCase()}.${ - chainIdToChainflipNetwork[step.sellAsset.chainId as KnownChainIds] - }` - const buyChainflipChainKey = `${step.buyAsset.symbol.toLowerCase()}.${ - chainIdToChainflipNetwork[step.buyAsset.chainId as KnownChainIds] - }` + const sourceAsset = await getChainFlipIdFromAssetId({ + assetId: step.sellAsset.assetId, + brokerUrl, + }) + const destinationAsset = await getChainFlipIdFromAssetId({ + assetId: step.buyAsset.assetId, + brokerUrl, + }) // Subtract the BaaS fee to end up at the final displayed commissionBps let serviceCommission = parseInt(tradeQuote.affiliateBps) - CHAINFLIP_BAAS_COMMISSION @@ -259,8 +270,8 @@ export const chainflipApi: SwapperApi = { const maybeSwapResponse = await getChainFlipSwap({ brokerUrl, apiKey, - sourceAsset: sellChainflipChainKey, - destinationAsset: buyChainflipChainKey, + sourceAsset, + destinationAsset, destinationAddress: tradeQuote.receiveAddress, minimumPrice, refundAddress: from, diff --git a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts index 59e72f1d3c8..9b2235f6cce 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts @@ -32,14 +32,13 @@ import { CHAINFLIP_DCA_SWAP_SOURCE, CHAINFLIP_REGULAR_QUOTE, CHAINFLIP_SWAP_SOURCE, - chainIdToChainflipNetwork, usdcAsset, } from '../constants' import type { ChainflipBaasQuoteQuote, ChainflipBaasQuoteQuoteFee } from '../models' import { chainflipService } from '../utils/chainflipService' import { getEvmTxFees } from '../utils/getEvmTxFees' import { getUtxoTxFees } from '../utils/getUtxoTxFees' -import { isSupportedAssetId, isSupportedChainId } from '../utils/helpers' +import { getChainFlipIdFromAssetId, isSupportedAssetId, isSupportedChainId } from '../utils/helpers' const _getTradeQuote = async ( input: CommonTradeQuoteInput, @@ -94,16 +93,18 @@ const _getTradeQuote = async ( ) } - const sellChainflipChainKey = `${sellAsset.symbol.toLowerCase()}.${ - chainIdToChainflipNetwork[sellAsset.chainId] - }` - const buyChainflipChainKey = `${buyAsset.symbol.toLowerCase()}.${ - chainIdToChainflipNetwork[buyAsset.chainId] - }` - const brokerUrl = deps.config.REACT_APP_CHAINFLIP_API_URL const apiKey = deps.config.REACT_APP_CHAINFLIP_API_KEY + const sourceAsset = await getChainFlipIdFromAssetId({ + assetId: sellAsset.assetId, + brokerUrl, + }) + const destinationAsset = await getChainFlipIdFromAssetId({ + assetId: buyAsset.assetId, + brokerUrl, + }) + // Subtract the BaaS fee to end up at the final displayed commissionBps let serviceCommission = parseInt(commissionBps) - CHAINFLIP_BAAS_COMMISSION if (serviceCommission < 0) serviceCommission = 0 @@ -111,8 +112,8 @@ const _getTradeQuote = async ( const maybeQuoteResponse = await chainflipService.get( `${brokerUrl}/quotes-native` + `?apiKey=${apiKey}` + - `&sourceAsset=${sellChainflipChainKey}` + - `&destinationAsset=${buyChainflipChainKey}` + + `&sourceAsset=${sourceAsset}` + + `&destinationAsset=${destinationAsset}` + `&amount=${sellAmount}` + `&commissionBps=${serviceCommission}`, ) @@ -152,7 +153,7 @@ const _getTradeQuote = async ( const networkFeeCryptoBaseUnit = await getEvmTxFees({ adapter: sellAdapter, supportsEIP1559: (input as GetEvmTradeQuoteInput).supportsEIP1559, - sendAsset: sellChainflipChainKey, + sendAsset: sourceAsset, }) return { networkFeeCryptoBaseUnit } } @@ -197,9 +198,9 @@ const _getTradeQuote = async ( if (fee.type === 'egress') return buyAsset - if (fee.type === 'liquidity' && fee.asset === sellChainflipChainKey) return sellAsset + if (fee.type === 'liquidity' && fee.asset === sourceAsset) return sellAsset - if (fee.type === 'liquidity' && fee.asset === buyChainflipChainKey) return buyAsset + if (fee.type === 'liquidity' && fee.asset === destinationAsset) return buyAsset if (fee.type === 'liquidity' && fee.asset === 'usdc.eth') return usdcAsset diff --git a/packages/swapper/src/swappers/ChainflipSwapper/types.ts b/packages/swapper/src/swappers/ChainflipSwapper/types.ts index 44411595176..da6b02fb57f 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/types.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/types.ts @@ -8,3 +8,10 @@ export type ChainFlipStatus = { swapEgress?: ChainflipBaasStatusEgress } } + +export enum ChainflipNetwork { + Bitcoin = 'Bitcoin', + Ethereum = 'Ethereum', + Arbitrum = 'Arbitrum', + Solana = 'Solana', +} diff --git a/packages/swapper/src/swappers/ChainflipSwapper/utils/helpers.ts b/packages/swapper/src/swappers/ChainflipSwapper/utils/helpers.ts index af144263558..c8db9aef664 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/utils/helpers.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/utils/helpers.ts @@ -1,18 +1,27 @@ -import { type AssetId, type ChainId } from '@shapeshiftoss/caip' +import { type AssetId, type ChainId, fromAssetId } from '@shapeshiftoss/caip' import type { Asset } from '@shapeshiftoss/types' import { bn, bnOrZero, fromBaseUnit } from '@shapeshiftoss/utils' import type { Result } from '@sniptt/monads' import type { AxiosResponse } from 'axios' import type { SwapErrorRight } from '../../../types' +import { isToken } from '../../../utils' import type { ChainflipSupportedChainId } from '../constants' -import { ChainflipSupportedAssetIdsByChainId, ChainflipSupportedChainIds } from '../constants' +import { + ChainflipSupportedAssetIdsByChainId, + ChainflipSupportedChainIds, + chainIdToChainflipNetwork, +} from '../constants' import type { ChainflipBaasSwapDepositAddress } from '../models' +import type { ChainflipNetwork } from '../types' import { chainflipService } from './chainflipService' -type GetChainFlipSwapArgs = { +type ChainFlipBrokerBaseArgs = { brokerUrl: string apiKey: string +} + +type GetChainFlipSwapArgs = ChainFlipBrokerBaseArgs & { sourceAsset: string destinationAsset: string destinationAddress: string @@ -23,6 +32,14 @@ type GetChainFlipSwapArgs = { commissionBps: number } +type ChainflipAsset = { + id: string + ticker: string + name: string + network: ChainflipNetwork + contractAddress?: string +} + export const isSupportedChainId = (chainId: ChainId): chainId is ChainflipSupportedChainId => { return ChainflipSupportedChainIds.includes(chainId as ChainflipSupportedChainId) } @@ -96,3 +113,41 @@ export const getChainFlipSwap = ({ `&retryDurationInBlocks=${retryDurationInBlocks}` + `&commissionBps=${commissionBps}`, ) + +const fetchChainFlipAssets = async ({ + brokerUrl, +}: Omit): Promise => { + const result = await chainflipService.get<{ assets: ChainflipAsset[] }>(`${brokerUrl}/assets`) + + if (result.isErr()) throw result.unwrapErr() + + const { data } = result.unwrap() + + return data.assets +} + +export const getChainFlipIdFromAssetId = async ({ + assetId, + brokerUrl, +}: Omit & { assetId: AssetId }) => { + const chainflipAssets = await fetchChainFlipAssets({ + brokerUrl, + }) + const { assetReference, chainId } = fromAssetId(assetId) + const _isToken = isToken(assetId) + + const chainflipAsset = chainflipAssets.find(asset => { + const isCorrectNetwork = asset.network === chainIdToChainflipNetwork[chainId] + if (!isCorrectNetwork) return false + + if (_isToken) { + return asset.contractAddress?.toLowerCase() === assetReference.toLowerCase() + } + + return !asset.contractAddress + }) + + if (!chainflipAsset) throw new Error('Asset not found') + + return chainflipAsset.id +} From 38492b010512e005b54d95c207d3c6e6fef2a004 Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Wed, 13 Nov 2024 18:08:12 +0700 Subject: [PATCH 093/127] feat: remove derp monkey patches --- src/components/TradeAssetSearch/TradeAssetSearch.tsx | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/components/TradeAssetSearch/TradeAssetSearch.tsx b/src/components/TradeAssetSearch/TradeAssetSearch.tsx index 59cbe358353..33bec7ade3d 100644 --- a/src/components/TradeAssetSearch/TradeAssetSearch.tsx +++ b/src/components/TradeAssetSearch/TradeAssetSearch.tsx @@ -106,9 +106,7 @@ export const TradeAssetSearch: FC = ({ const handleSubmit = useCallback((e: FormEvent) => e.preventDefault(), []) const popularAssets = useMemo(() => { - const unfilteredPopularAssets = (popularAssetsByChainId?.[activeChainId] ?? []).filter(asset => - isSwapper ? asset.chainId !== KnownChainIds.SolanaMainnet : true, - ) + const unfilteredPopularAssets = popularAssetsByChainId?.[activeChainId] ?? [] if (allowWalletUnsupportedAssets || !hasWallet) return unfilteredPopularAssets return unfilteredPopularAssets.filter(asset => walletConnectedChainIds.includes(asset.chainId)) }, [ @@ -117,7 +115,6 @@ export const TradeAssetSearch: FC = ({ allowWalletUnsupportedAssets, hasWallet, walletConnectedChainIds, - isSwapper, ]) const quickAccessAssets = useMemo(() => { @@ -145,13 +142,11 @@ export const TradeAssetSearch: FC = ({ const portfolioAssetsSortedByBalanceForChain = useMemo(() => { if (activeChainId === 'All') { - return portfolioAssetsSortedByBalance.filter(asset => - isSwapper ? asset.chainId !== KnownChainIds.SolanaMainnet : true, - ) + return portfolioAssetsSortedByBalance } return portfolioAssetsSortedByBalance.filter(asset => asset.chainId === activeChainId) - }, [activeChainId, portfolioAssetsSortedByBalance, isSwapper]) + }, [activeChainId, portfolioAssetsSortedByBalance]) const chainIds: (ChainId | 'All')[] = useMemo(() => { const unsortedChainIds = (() => { From b514351db9f520f4e041e9d61bf7f9104e4bde09 Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Wed, 13 Nov 2024 18:10:07 +0700 Subject: [PATCH 094/127] feat: and search too --- .../components/SearchTermAssetList.tsx | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/components/TradeAssetSearch/components/SearchTermAssetList.tsx b/src/components/TradeAssetSearch/components/SearchTermAssetList.tsx index 438d1b7195f..a45b9a980c4 100644 --- a/src/components/TradeAssetSearch/components/SearchTermAssetList.tsx +++ b/src/components/TradeAssetSearch/components/SearchTermAssetList.tsx @@ -1,6 +1,6 @@ import { ASSET_NAMESPACE, bscChainId, type ChainId, toAssetId } from '@shapeshiftoss/caip' import { isEvmChainId } from '@shapeshiftoss/chain-adapters' -import { type Asset, KnownChainIds } from '@shapeshiftoss/types' +import { type Asset } from '@shapeshiftoss/types' import { bnOrZero, makeAsset, type MinimalAsset } from '@shapeshiftoss/utils' import { orderBy } from 'lodash' import { useMemo } from 'react' @@ -58,18 +58,15 @@ export const SearchTermAssetList = ({ const assetsForChain = useMemo(() => { if (activeChainId === 'All') { - const _assets = assets.filter(asset => - isSwapper ? asset.chainId !== KnownChainIds.SolanaMainnet : true, - ) - if (allowWalletUnsupportedAssets) return _assets - return _assets.filter(asset => walletConnectedChainIds.includes(asset.chainId)) + if (allowWalletUnsupportedAssets) return assets + return assets.filter(asset => walletConnectedChainIds.includes(asset.chainId)) } // Should never happen, but paranoia. if (!allowWalletUnsupportedAssets && !walletConnectedChainIds.includes(activeChainId)) return [] return assets.filter(asset => asset.chainId === activeChainId) - }, [activeChainId, allowWalletUnsupportedAssets, assets, walletConnectedChainIds, isSwapper]) + }, [activeChainId, allowWalletUnsupportedAssets, assets, walletConnectedChainIds]) const customAssets: Asset[] = useMemo( () => From 9ea3859e27f2be8f1ae761c713ad8aab40f1176c Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Wed, 13 Nov 2024 18:11:19 +0700 Subject: [PATCH 095/127] feat: cleanup isSwapper --- src/components/TradeAssetSearch/TradeAssetSearch.tsx | 3 --- .../TradeAssetSearch/components/SearchTermAssetList.tsx | 2 -- 2 files changed, 5 deletions(-) diff --git a/src/components/TradeAssetSearch/TradeAssetSearch.tsx b/src/components/TradeAssetSearch/TradeAssetSearch.tsx index 33bec7ade3d..c9f0d433fa7 100644 --- a/src/components/TradeAssetSearch/TradeAssetSearch.tsx +++ b/src/components/TradeAssetSearch/TradeAssetSearch.tsx @@ -45,13 +45,11 @@ export type TradeAssetSearchProps = { onAssetClick?: (asset: Asset) => void formProps?: BoxProps allowWalletUnsupportedAssets?: boolean - isSwapper?: boolean } export const TradeAssetSearch: FC = ({ onAssetClick, formProps, allowWalletUnsupportedAssets, - isSwapper, }) => { const { walletInfo } = useWallet().state const hasWallet = useMemo(() => Boolean(walletInfo?.deviceId), [walletInfo?.deviceId]) @@ -239,7 +237,6 @@ export const TradeAssetSearch: FC = ({ onAssetClick={handleAssetClick} onImportClick={handleImportIntent} isLoading={isPopularAssetIdsLoading} - isSwapper={isSwapper} allowWalletUnsupportedAssets={!hasWallet || allowWalletUnsupportedAssets} /> ) : ( diff --git a/src/components/TradeAssetSearch/components/SearchTermAssetList.tsx b/src/components/TradeAssetSearch/components/SearchTermAssetList.tsx index a45b9a980c4..7f7574da410 100644 --- a/src/components/TradeAssetSearch/components/SearchTermAssetList.tsx +++ b/src/components/TradeAssetSearch/components/SearchTermAssetList.tsx @@ -23,7 +23,6 @@ export type SearchTermAssetListProps = { activeChainId: ChainId | 'All' searchString: string allowWalletUnsupportedAssets: boolean | undefined - isSwapper?: boolean onAssetClick: (asset: Asset) => void onImportClick: (asset: Asset) => void } @@ -33,7 +32,6 @@ export const SearchTermAssetList = ({ activeChainId, searchString, allowWalletUnsupportedAssets, - isSwapper, onAssetClick: handleAssetClick, onImportClick, }: SearchTermAssetListProps) => { From 204902fa347a7f67edd4ffb13ca471d7a4b38811 Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Wed, 13 Nov 2024 18:15:21 +0700 Subject: [PATCH 096/127] fix: derp --- src/components/Modals/TradeAssetSearch/TradeAssetSearchModal.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/Modals/TradeAssetSearch/TradeAssetSearchModal.tsx b/src/components/Modals/TradeAssetSearch/TradeAssetSearchModal.tsx index d5eed145f12..a69a65504b0 100644 --- a/src/components/Modals/TradeAssetSearch/TradeAssetSearchModal.tsx +++ b/src/components/Modals/TradeAssetSearch/TradeAssetSearchModal.tsx @@ -50,7 +50,6 @@ export const TradeAssetSearchModalBase: FC = ({ ) From cf52fd46377c0c0815491c7917fa63dc8a85e8ae Mon Sep 17 00:00:00 2001 From: NeOMakinG <14963751+NeOMakinG@users.noreply.github.com> Date: Wed, 13 Nov 2024 15:09:49 +0100 Subject: [PATCH 097/127] fix: continue --- .env.base | 1 + .env.dev | 1 + packages/swapper/src/constants.ts | 12 + .../src/swappers/JupiterSwapper/endpoints.ts | 30 +- .../JupiterSwapper/models/PlatformFee.ts | 73 +++++ .../JupiterSwapper/models/QuoteResponse.ts | 189 ++++++++++++ .../JupiterSwapper/models/RoutePlanStep.ts | 82 +++++ .../JupiterSwapper/models/SwapInfo.ts | 128 ++++++++ .../JupiterSwapper/models/SwapMode.ts | 38 +++ .../swapperApi/getTradeQuote.ts | 286 +++--------------- .../JupiterSwapper/utils/constants.ts | 8 + .../swappers/JupiterSwapper/utils/helpers.ts | 40 ++- .../JupiterSwapper/utils/jupiterService.ts | 20 ++ packages/swapper/src/types.ts | 6 +- .../components/SwapperIcon/SwapperIcon.tsx | 3 + .../components/SwapperIcon/jupiter-icon.svg | 51 ++++ src/config.ts | 2 + src/state/helpers.ts | 14 +- .../preferencesSlice/preferencesSlice.ts | 2 + src/test/mocks/store.ts | 1 + 20 files changed, 713 insertions(+), 274 deletions(-) create mode 100644 packages/swapper/src/swappers/JupiterSwapper/models/PlatformFee.ts create mode 100644 packages/swapper/src/swappers/JupiterSwapper/models/QuoteResponse.ts create mode 100644 packages/swapper/src/swappers/JupiterSwapper/models/RoutePlanStep.ts create mode 100644 packages/swapper/src/swappers/JupiterSwapper/models/SwapInfo.ts create mode 100644 packages/swapper/src/swappers/JupiterSwapper/models/SwapMode.ts create mode 100644 packages/swapper/src/swappers/JupiterSwapper/utils/jupiterService.ts create mode 100644 src/components/MultiHopTrade/components/TradeInput/components/SwapperIcon/jupiter-icon.svg diff --git a/.env.base b/.env.base index 88bc07586b1..317f87dbb9a 100644 --- a/.env.base +++ b/.env.base @@ -68,6 +68,7 @@ REACT_APP_FEATURE_LIFI_SWAP=true REACT_APP_FEATURE_THOR_SWAP=true REACT_APP_FEATURE_THOR_SWAP_STREAMING_SWAPS=true REACT_APP_FEATURE_ZRX_SWAP=true +REACT_APP_FEATURE_JUPITER=false # chat woot REACT_APP_CHATWOOT_TOKEN=jmoXp9BPMSPEYHeJX5YKT15Q diff --git a/.env.dev b/.env.dev index d4a43eab718..cbc7d7610e7 100644 --- a/.env.dev +++ b/.env.dev @@ -3,6 +3,7 @@ REACT_APP_FEATURE_CHAINFLIP=true REACT_APP_FEATURE_CHAINFLIP_DCA=false REACT_APP_FEATURE_PUBLIC_TRADE_ROUTE=false REACT_APP_FEATURE_LIMIT_ORDERS=true +REACT_APP_FEATURE_JUPITER=true # logging REACT_APP_REDUX_WINDOW=false diff --git a/packages/swapper/src/constants.ts b/packages/swapper/src/constants.ts index 9a60ff3745d..e487c90adbb 100644 --- a/packages/swapper/src/constants.ts +++ b/packages/swapper/src/constants.ts @@ -9,6 +9,9 @@ import { chainflipApi } from './swappers/ChainflipSwapper/endpoints' import { cowSwapper } from './swappers/CowSwapper/CowSwapper' import { cowApi } from './swappers/CowSwapper/endpoints' import { COW_SWAP_SUPPORTED_CHAIN_IDS } from './swappers/CowSwapper/utils/constants' +import { jupiterApi } from './swappers/JupiterSwapper/endpoints' +import { jupiterSwapper } from './swappers/JupiterSwapper/JupiterSwapper' +import { JUPITER_SUPPORTED_CHAIN_IDS } from './swappers/JupiterSwapper/utils/constants' import { lifiApi } from './swappers/LifiSwapper/endpoints' import { LIFI_GET_TRADE_QUOTE_POLLING_INTERVAL, @@ -85,6 +88,12 @@ export const swappers: Record< supportedChainIds: CHAINFLIP_SUPPORTED_CHAIN_IDS, pollingInterval: DEFAULT_GET_TRADE_QUOTE_POLLING_INTERVAL, }, + [SwapperName.Jupiter]: { + ...jupiterSwapper, + ...jupiterApi, + supportedChainIds: JUPITER_SUPPORTED_CHAIN_IDS, + pollingInterval: DEFAULT_GET_TRADE_QUOTE_POLLING_INTERVAL, + }, [SwapperName.Test]: undefined, } @@ -96,6 +105,7 @@ const DEFAULT_LIFI_SLIPPAGE_DECIMAL_PERCENTAGE = '0.005' // .5% const DEFAULT_THOR_SLIPPAGE_DECIMAL_PERCENTAGE = '0.01' // 1% const DEFAULT_ARBITRUM_BRIDGE_SLIPPAGE_DECIMAL_PERCENTAGE = '0' // no slippage for Arbitrum Bridge, so no slippage tolerance const DEFAULT_CHAINFLIP_SLIPPAGE_DECIMAL_PERCENTAGE = '0.02' // 2% +const DEFAULT_JUPITER_SLIPPAGE_DECIMAL_PERCENTAGE = '0.005' // .5% export const getDefaultSlippageDecimalPercentageForSwapper = ( swapperName?: SwapperName, @@ -117,6 +127,8 @@ export const getDefaultSlippageDecimalPercentageForSwapper = ( return DEFAULT_ARBITRUM_BRIDGE_SLIPPAGE_DECIMAL_PERCENTAGE case SwapperName.Chainflip: return DEFAULT_CHAINFLIP_SLIPPAGE_DECIMAL_PERCENTAGE + case SwapperName.Jupiter: + return DEFAULT_JUPITER_SLIPPAGE_DECIMAL_PERCENTAGE default: assertUnreachable(swapperName) } diff --git a/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts b/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts index bc7ad7edf05..926987c9dfe 100644 --- a/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts +++ b/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts @@ -1,40 +1,20 @@ import { fromChainId } from '@shapeshiftoss/caip' import type { SolanaSignTx } from '@shapeshiftoss/hdwallet-core' import { TxStatus } from '@shapeshiftoss/unchained-client' -import type { Result } from '@sniptt/monads/build' import type { InterpolationOptions } from 'node-polyglot' -import type { - CommonTradeQuoteInput, - GetUnsignedSolanaTransactionArgs, - TradeRate, -} from '../../types' -import { - type GetTradeQuoteInput, - type SwapErrorRight, - type SwapperApi, - type TradeQuote, -} from '../../types' +import type { GetUnsignedSolanaTransactionArgs } from '../../types' +import { type SwapperApi } from '../../types' import { isExecutableTradeQuote } from '../../utils' +import { getTradeQuote, getTradeRate } from './swapperApi/getTradeQuote' export const jupiterApi: SwapperApi = { - getTradeQuote: ( - input: CommonTradeQuoteInput, - // { assertGetSolanaChainAdapter, assetsById, config }: SwapperDeps, - ): Promise> => { - return [] as unknown as Promise> - }, - getTradeRate: ( - input: GetTradeQuoteInput, - // { assertGetSolanaChainAdapter, assetsById, config }: SwapperDeps, - ): Promise> => { - return [] as unknown as Promise> - }, + getTradeQuote, + getTradeRate, getUnsignedSolanaTransaction: ({ chainId, from, tradeQuote, - config, }: GetUnsignedSolanaTransactionArgs): Promise => { if (!isExecutableTradeQuote(tradeQuote)) throw new Error('Unable to execute trade') diff --git a/packages/swapper/src/swappers/JupiterSwapper/models/PlatformFee.ts b/packages/swapper/src/swappers/JupiterSwapper/models/PlatformFee.ts new file mode 100644 index 00000000000..7b318eed167 --- /dev/null +++ b/packages/swapper/src/swappers/JupiterSwapper/models/PlatformFee.ts @@ -0,0 +1,73 @@ +// @ts-nocheck +/* tslint:disable */ +/* eslint-disable */ +/** + * Jupiter API v6 + * The core of [jup.ag](https://jup.ag). Easily get a quote and swap through Jupiter API. ### Rate Limit We update our rate limit from time to time depending on the load of our servers. We recommend running your own instance of the API if you want to have high rate limit, here to learn how to run the [self-hosted API](https://station.jup.ag/docs/apis/self-hosted). ### API Wrapper - Typescript [@jup-ag/api](https://github.com/jup-ag/jupiter-quote-api-node) ### Data types - Public keys are base58 encoded strings - raw data such as Vec are base64 encoded strings + * + * The version of the OpenAPI document: 6.0.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +/** + * + * @export + * @interface PlatformFee + */ +export interface PlatformFee { + /** + * + * @type {string} + * @memberof PlatformFee + */ + amount?: string; + /** + * + * @type {number} + * @memberof PlatformFee + */ + feeBps?: number; +} + +/** + * Check if a given object implements the PlatformFee interface. + */ +export function instanceOfPlatformFee(value: object): boolean { + let isInstance = true; + + return isInstance; +} + +export function PlatformFeeFromJSON(json: any): PlatformFee { + return PlatformFeeFromJSONTyped(json, false); +} + +export function PlatformFeeFromJSONTyped(json: any, ignoreDiscriminator: boolean): PlatformFee { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'amount': !exists(json, 'amount') ? undefined : json['amount'], + 'feeBps': !exists(json, 'feeBps') ? undefined : json['feeBps'], + }; +} + +export function PlatformFeeToJSON(value?: PlatformFee | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'amount': value.amount, + 'feeBps': value.feeBps, + }; +} diff --git a/packages/swapper/src/swappers/JupiterSwapper/models/QuoteResponse.ts b/packages/swapper/src/swappers/JupiterSwapper/models/QuoteResponse.ts new file mode 100644 index 00000000000..92fec184a40 --- /dev/null +++ b/packages/swapper/src/swappers/JupiterSwapper/models/QuoteResponse.ts @@ -0,0 +1,189 @@ +// @ts-nocheck +/* tslint:disable */ +/* eslint-disable */ +/** + * Jupiter API v6 + * The core of [jup.ag](https://jup.ag). Easily get a quote and swap through Jupiter API. ### Rate Limit We update our rate limit from time to time depending on the load of our servers. We recommend running your own instance of the API if you want to have high rate limit, here to learn how to run the [self-hosted API](https://station.jup.ag/docs/apis/self-hosted). ### API Wrapper - Typescript [@jup-ag/api](https://github.com/jup-ag/jupiter-quote-api-node) ### Data types - Public keys are base58 encoded strings - raw data such as Vec are base64 encoded strings + * + * The version of the OpenAPI document: 6.0.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +import type { PlatformFee } from './PlatformFee'; +import { + PlatformFeeFromJSON, + PlatformFeeFromJSONTyped, + PlatformFeeToJSON, +} from './PlatformFee'; +import type { RoutePlanStep } from './RoutePlanStep.ts'; +import { + RoutePlanStepFromJSON, + RoutePlanStepFromJSONTyped, + RoutePlanStepToJSON, +} from './RoutePlanStep.ts'; +import type { SwapMode } from './SwapMode'; +import { + SwapModeFromJSON, + SwapModeFromJSONTyped, + SwapModeToJSON, +} from './SwapMode'; + +/** + * + * @export + * @interface QuoteResponse + */ +export interface QuoteResponse { + /** + * + * @type {string} + * @memberof QuoteResponse + */ + inputMint: string; + /** + * + * @type {string} + * @memberof QuoteResponse + */ + inAmount: string; + /** + * + * @type {string} + * @memberof QuoteResponse + */ + outputMint: string; + /** + * + * @type {string} + * @memberof QuoteResponse + */ + outAmount: string; + /** + * + * @type {string} + * @memberof QuoteResponse + */ + otherAmountThreshold: string; + /** + * + * @type {SwapMode} + * @memberof QuoteResponse + */ + swapMode: SwapMode; + /** + * + * @type {number} + * @memberof QuoteResponse + */ + slippageBps: number; + /** + * + * @type {number} + * @memberof QuoteResponse + */ + computedAutoSlippage?: number; + /** + * + * @type {PlatformFee} + * @memberof QuoteResponse + */ + platformFee?: PlatformFee; + /** + * + * @type {string} + * @memberof QuoteResponse + */ + priceImpactPct: string; + /** + * + * @type {Array} + * @memberof QuoteResponse + */ + routePlan: Array; + /** + * + * @type {number} + * @memberof QuoteResponse + */ + contextSlot?: number; + /** + * + * @type {number} + * @memberof QuoteResponse + */ + timeTaken?: number; +} + +/** + * Check if a given object implements the QuoteResponse interface. + */ +export function instanceOfQuoteResponse(value: object): boolean { + let isInstance = true; + isInstance = isInstance && "inputMint" in value; + isInstance = isInstance && "inAmount" in value; + isInstance = isInstance && "outputMint" in value; + isInstance = isInstance && "outAmount" in value; + isInstance = isInstance && "otherAmountThreshold" in value; + isInstance = isInstance && "swapMode" in value; + isInstance = isInstance && "slippageBps" in value; + isInstance = isInstance && "priceImpactPct" in value; + isInstance = isInstance && "routePlan" in value; + + return isInstance; +} + +export function QuoteResponseFromJSON(json: any): QuoteResponse { + return QuoteResponseFromJSONTyped(json, false); +} + +export function QuoteResponseFromJSONTyped(json: any, ignoreDiscriminator: boolean): QuoteResponse { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'inputMint': json['inputMint'], + 'inAmount': json['inAmount'], + 'outputMint': json['outputMint'], + 'outAmount': json['outAmount'], + 'otherAmountThreshold': json['otherAmountThreshold'], + 'swapMode': SwapModeFromJSON(json['swapMode']), + 'slippageBps': json['slippageBps'], + 'computedAutoSlippage': !exists(json, 'computedAutoSlippage') ? undefined : json['computedAutoSlippage'], + 'platformFee': !exists(json, 'platformFee') ? undefined : PlatformFeeFromJSON(json['platformFee']), + 'priceImpactPct': json['priceImpactPct'], + 'routePlan': ((json['routePlan'] as Array).map(RoutePlanStepFromJSON)), + 'contextSlot': !exists(json, 'contextSlot') ? undefined : json['contextSlot'], + 'timeTaken': !exists(json, 'timeTaken') ? undefined : json['timeTaken'], + }; +} + +export function QuoteResponseToJSON(value?: QuoteResponse | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'inputMint': value.inputMint, + 'inAmount': value.inAmount, + 'outputMint': value.outputMint, + 'outAmount': value.outAmount, + 'otherAmountThreshold': value.otherAmountThreshold, + 'swapMode': SwapModeToJSON(value.swapMode), + 'slippageBps': value.slippageBps, + 'computedAutoSlippage': value.computedAutoSlippage, + 'platformFee': PlatformFeeToJSON(value.platformFee), + 'priceImpactPct': value.priceImpactPct, + 'routePlan': ((value.routePlan as Array).map(RoutePlanStepToJSON)), + 'contextSlot': value.contextSlot, + 'timeTaken': value.timeTaken, + }; +} diff --git a/packages/swapper/src/swappers/JupiterSwapper/models/RoutePlanStep.ts b/packages/swapper/src/swappers/JupiterSwapper/models/RoutePlanStep.ts new file mode 100644 index 00000000000..39ae6a22c5c --- /dev/null +++ b/packages/swapper/src/swappers/JupiterSwapper/models/RoutePlanStep.ts @@ -0,0 +1,82 @@ +// @ts-nocheck +/* tslint:disable */ +/* eslint-disable */ +/** + * Jupiter API v6 + * The core of [jup.ag](https://jup.ag). Easily get a quote and swap through Jupiter API. ### Rate Limit We update our rate limit from time to time depending on the load of our servers. We recommend running your own instance of the API if you want to have high rate limit, here to learn how to run the [self-hosted API](https://station.jup.ag/docs/apis/self-hosted). ### API Wrapper - Typescript [@jup-ag/api](https://github.com/jup-ag/jupiter-quote-api-node) ### Data types - Public keys are base58 encoded strings - raw data such as Vec are base64 encoded strings + * + * The version of the OpenAPI document: 6.0.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +import type { SwapInfo } from './SwapInfo'; +import { + SwapInfoFromJSON, + SwapInfoFromJSONTyped, + SwapInfoToJSON, +} from './SwapInfo'; + +/** + * + * @export + * @interface RoutePlanStep + */ +export interface RoutePlanStep { + /** + * + * @type {SwapInfo} + * @memberof RoutePlanStep + */ + swapInfo: SwapInfo; + /** + * + * @type {number} + * @memberof RoutePlanStep + */ + percent: number; +} + +/** + * Check if a given object implements the RoutePlanStep interface. + */ +export function instanceOfRoutePlanStep(value: object): boolean { + let isInstance = true; + isInstance = isInstance && "swapInfo" in value; + isInstance = isInstance && "percent" in value; + + return isInstance; +} + +export function RoutePlanStepFromJSON(json: any): RoutePlanStep { + return RoutePlanStepFromJSONTyped(json, false); +} + +export function RoutePlanStepFromJSONTyped(json: any, ignoreDiscriminator: boolean): RoutePlanStep { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'swapInfo': SwapInfoFromJSON(json['swapInfo']), + 'percent': json['percent'], + }; +} + +export function RoutePlanStepToJSON(value?: RoutePlanStep | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'swapInfo': SwapInfoToJSON(value.swapInfo), + 'percent': value.percent, + }; +} diff --git a/packages/swapper/src/swappers/JupiterSwapper/models/SwapInfo.ts b/packages/swapper/src/swappers/JupiterSwapper/models/SwapInfo.ts new file mode 100644 index 00000000000..4ee72ea7470 --- /dev/null +++ b/packages/swapper/src/swappers/JupiterSwapper/models/SwapInfo.ts @@ -0,0 +1,128 @@ +// @ts-nocheck +/* tslint:disable */ +/* eslint-disable */ +/** + * Jupiter API v6 + * The core of [jup.ag](https://jup.ag). Easily get a quote and swap through Jupiter API. ### Rate Limit We update our rate limit from time to time depending on the load of our servers. We recommend running your own instance of the API if you want to have high rate limit, here to learn how to run the [self-hosted API](https://station.jup.ag/docs/apis/self-hosted). ### API Wrapper - Typescript [@jup-ag/api](https://github.com/jup-ag/jupiter-quote-api-node) ### Data types - Public keys are base58 encoded strings - raw data such as Vec are base64 encoded strings + * + * The version of the OpenAPI document: 6.0.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +/** + * + * @export + * @interface SwapInfo + */ +export interface SwapInfo { + /** + * + * @type {string} + * @memberof SwapInfo + */ + ammKey: string; + /** + * + * @type {string} + * @memberof SwapInfo + */ + label?: string; + /** + * + * @type {string} + * @memberof SwapInfo + */ + inputMint: string; + /** + * + * @type {string} + * @memberof SwapInfo + */ + outputMint: string; + /** + * + * @type {string} + * @memberof SwapInfo + */ + inAmount: string; + /** + * + * @type {string} + * @memberof SwapInfo + */ + outAmount: string; + /** + * + * @type {string} + * @memberof SwapInfo + */ + feeAmount: string; + /** + * + * @type {string} + * @memberof SwapInfo + */ + feeMint: string; +} + +/** + * Check if a given object implements the SwapInfo interface. + */ +export function instanceOfSwapInfo(value: object): boolean { + let isInstance = true; + isInstance = isInstance && "ammKey" in value; + isInstance = isInstance && "inputMint" in value; + isInstance = isInstance && "outputMint" in value; + isInstance = isInstance && "inAmount" in value; + isInstance = isInstance && "outAmount" in value; + isInstance = isInstance && "feeAmount" in value; + isInstance = isInstance && "feeMint" in value; + + return isInstance; +} + +export function SwapInfoFromJSON(json: any): SwapInfo { + return SwapInfoFromJSONTyped(json, false); +} + +export function SwapInfoFromJSONTyped(json: any, ignoreDiscriminator: boolean): SwapInfo { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'ammKey': json['ammKey'], + 'label': !exists(json, 'label') ? undefined : json['label'], + 'inputMint': json['inputMint'], + 'outputMint': json['outputMint'], + 'inAmount': json['inAmount'], + 'outAmount': json['outAmount'], + 'feeAmount': json['feeAmount'], + 'feeMint': json['feeMint'], + }; +} + +export function SwapInfoToJSON(value?: SwapInfo | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'ammKey': value.ammKey, + 'label': value.label, + 'inputMint': value.inputMint, + 'outputMint': value.outputMint, + 'inAmount': value.inAmount, + 'outAmount': value.outAmount, + 'feeAmount': value.feeAmount, + 'feeMint': value.feeMint, + }; +} diff --git a/packages/swapper/src/swappers/JupiterSwapper/models/SwapMode.ts b/packages/swapper/src/swappers/JupiterSwapper/models/SwapMode.ts new file mode 100644 index 00000000000..63b5e3df433 --- /dev/null +++ b/packages/swapper/src/swappers/JupiterSwapper/models/SwapMode.ts @@ -0,0 +1,38 @@ +// @ts-nocheck +/* tslint:disable */ +/* eslint-disable */ +/** + * Jupiter API v6 + * The core of [jup.ag](https://jup.ag). Easily get a quote and swap through Jupiter API. ### Rate Limit We update our rate limit from time to time depending on the load of our servers. We recommend running your own instance of the API if you want to have high rate limit, here to learn how to run the [self-hosted API](https://station.jup.ag/docs/apis/self-hosted). ### API Wrapper - Typescript [@jup-ag/api](https://github.com/jup-ag/jupiter-quote-api-node) ### Data types - Public keys are base58 encoded strings - raw data such as Vec are base64 encoded strings + * + * The version of the OpenAPI document: 6.0.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +/** + * + * @export + */ +export const SwapMode = { + ExactIn: 'ExactIn', + ExactOut: 'ExactOut' +} as const; +export type SwapMode = typeof SwapMode[keyof typeof SwapMode]; + + +export function SwapModeFromJSON(json: any): SwapMode { + return SwapModeFromJSONTyped(json, false); +} + +export function SwapModeFromJSONTyped(json: any, ignoreDiscriminator: boolean): SwapMode { + return json as SwapMode; +} + +export function SwapModeToJSON(value?: SwapMode | null): any { + return value as any; +} diff --git a/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeQuote.ts b/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeQuote.ts index eb99c6d9c3a..3b53dd527d8 100644 --- a/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeQuote.ts +++ b/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeQuote.ts @@ -1,45 +1,22 @@ -import type { AssetId } from '@shapeshiftoss/caip' import { CHAIN_NAMESPACE, fromAssetId, solAssetId } from '@shapeshiftoss/caip' import type { GetFeeDataInput } from '@shapeshiftoss/chain-adapters' import type { KnownChainIds } from '@shapeshiftoss/types' import type { Result } from '@sniptt/monads' import { Err, Ok } from '@sniptt/monads' -import type { AxiosError } from 'axios' import { v4 as uuid } from 'uuid' import { getDefaultSlippageDecimalPercentageForSwapper } from '../../../constants' import type { CommonTradeQuoteInput, GetTradeRateInput, - GetUtxoTradeQuoteInput, SwapErrorRight, SwapperDeps, TradeQuote, TradeRate, } from '../../../types' -import { - type GetEvmTradeQuoteInput, - type ProtocolFee, - SwapperName, - TradeQuoteError, -} from '../../../types' +import { SwapperName, TradeQuoteError } from '../../../types' import { getRate, makeSwapErrorRight } from '../../../utils' -import { - CHAINFLIP_BAAS_COMMISSION, - CHAINFLIP_BOOST_SWAP_SOURCE, - CHAINFLIP_DCA_BOOST_SWAP_SOURCE, - CHAINFLIP_DCA_QUOTE, - CHAINFLIP_DCA_SWAP_SOURCE, - CHAINFLIP_REGULAR_QUOTE, - CHAINFLIP_SWAP_SOURCE, - chainIdToChainflipNetwork, - usdcAsset, -} from '../constants' -import type { ChainflipBaasQuoteQuote, ChainflipBaasQuoteQuoteFee } from '../models' -import { chainflipService } from '../utils/chainflipService' -import { getEvmTxFees } from '../utils/getEvmTxFees' -import { getUtxoTxFees } from '../utils/getUtxoTxFees' -import { isSupportedAssetId, isSupportedChainId } from '../utils/helpers' +import { getJupiterSwap, isSupportedChainId } from '../utils/helpers' const _getTradeQuote = async ( input: CommonTradeQuoteInput, @@ -48,12 +25,15 @@ const _getTradeQuote = async ( const { sellAsset, buyAsset, - accountNumber, - receiveAddress, sellAmountIncludingProtocolFeesCryptoBaseUnit: sellAmount, - affiliateBps: commissionBps, + affiliateBps, + receiveAddress, + accountNumber, + slippageTolerancePercentageDecimal, } = input + const jupiterUrl = deps.config.REACT_APP_JUPITER_API_URL + if (!isSupportedChainId(sellAsset.chainId)) { return Err( makeSwapErrorRight({ @@ -74,65 +54,16 @@ const _getTradeQuote = async ( ) } - if (!isSupportedAssetId(sellAsset.chainId, sellAsset.assetId)) { - return Err( - makeSwapErrorRight({ - message: `asset '${sellAsset.name}' on chainId '${sellAsset.chainId}' not supported`, - code: TradeQuoteError.UnsupportedTradePair, - details: { chainId: sellAsset.chainId, assetId: sellAsset.assetId }, - }), - ) - } - - if (!isSupportedAssetId(buyAsset.chainId, buyAsset.assetId)) { - return Err( - makeSwapErrorRight({ - message: `asset '${buyAsset.name}' on chainId '${buyAsset.chainId}' not supported`, - code: TradeQuoteError.UnsupportedTradePair, - details: { chainId: buyAsset.chainId, assetId: buyAsset.assetId }, - }), - ) - } - - const sellChainflipChainKey = `${sellAsset.symbol.toLowerCase()}.${ - chainIdToChainflipNetwork[sellAsset.chainId] - }` - const buyChainflipChainKey = `${buyAsset.symbol.toLowerCase()}.${ - chainIdToChainflipNetwork[buyAsset.chainId] - }` - - const brokerUrl = deps.config.REACT_APP_CHAINFLIP_API_URL - const apiKey = deps.config.REACT_APP_CHAINFLIP_API_KEY - - // Subtract the BaaS fee to end up at the final displayed commissionBps - let serviceCommission = parseInt(commissionBps) - CHAINFLIP_BAAS_COMMISSION - if (serviceCommission < 0) serviceCommission = 0 - - const maybeQuoteResponse = await chainflipService.get( - `${brokerUrl}/quotes-native` + - `?apiKey=${apiKey}` + - `&sourceAsset=${sellChainflipChainKey}` + - `&destinationAsset=${buyChainflipChainKey}` + - `&amount=${sellAmount}` + - `&commissionBps=${serviceCommission}`, - ) + const maybeQuoteResponse = await getJupiterSwap({ + apiUrl: jupiterUrl, + sourceAsset: sellAsset.assetId, + destinationAsset: buyAsset.assetId, + commissionBps: affiliateBps, + amount: sellAmount, + slippageBps: slippageTolerancePercentageDecimal, + }) if (maybeQuoteResponse.isErr()) { - const error = maybeQuoteResponse.unwrapErr() - const cause = error.cause as AxiosError - - if ( - cause.message.includes('code 400') && - cause.response!.data.detail.includes('Amount outside asset bounds') - ) { - return Err( - makeSwapErrorRight({ - message: cause.response!.data.detail, - code: TradeQuoteError.SellAmountBelowMinimum, - }), - ) - } - return Err( makeSwapErrorRight({ message: 'Quote request failed', @@ -147,28 +78,6 @@ const _getTradeQuote = async ( const { chainNamespace } = fromAssetId(sellAsset.assetId) switch (chainNamespace) { - case CHAIN_NAMESPACE.Evm: { - const sellAdapter = deps.assertGetEvmChainAdapter(sellAsset.chainId) - const networkFeeCryptoBaseUnit = await getEvmTxFees({ - adapter: sellAdapter, - supportsEIP1559: (input as GetEvmTradeQuoteInput).supportsEIP1559, - sendAsset: sellChainflipChainKey, - }) - return { networkFeeCryptoBaseUnit } - } - - case CHAIN_NAMESPACE.Utxo: { - const sellAdapter = deps.assertGetUtxoChainAdapter(sellAsset.chainId) - const publicKey = (input as GetUtxoTradeQuoteInput).xpub! - const feeData = await getUtxoTxFees({ - sellAmountCryptoBaseUnit: sellAmount, - sellAdapter, - publicKey, - }) - - return feeData - } - case CHAIN_NAMESPACE.Solana: { const sellAdapter = deps.assertGetSolanaChainAdapter(sellAsset.chainId) const getFeeDataInput: GetFeeDataInput = { @@ -192,43 +101,6 @@ const _getTradeQuote = async ( } } - const getFeeAsset = (fee: ChainflipBaasQuoteQuoteFee) => { - if (fee.type === 'ingress' || fee.type === 'boost') return sellAsset - - if (fee.type === 'egress') return buyAsset - - if (fee.type === 'liquidity' && fee.asset === sellChainflipChainKey) return sellAsset - - if (fee.type === 'liquidity' && fee.asset === buyChainflipChainKey) return buyAsset - - if (fee.type === 'liquidity' && fee.asset === 'usdc.eth') return usdcAsset - - if (fee.type === 'network') return usdcAsset - } - - const getProtocolFees = (singleQuoteResponse: ChainflipBaasQuoteQuote) => { - const protocolFees: Record = {} - - for (const fee of singleQuoteResponse.includedFees!) { - if (fee.type === 'broker') continue - - const asset = getFeeAsset(fee)! - if (!(asset.assetId in protocolFees)) { - protocolFees[asset.assetId] = { - amountCryptoBaseUnit: '0', - requiresBalance: false, - asset, - } - } - - protocolFees[asset.assetId].amountCryptoBaseUnit = ( - BigInt(protocolFees[asset.assetId].amountCryptoBaseUnit) + BigInt(fee.amountNative!) - ).toString() - } - - return protocolFees - } - const getQuoteRate = (sellAmountCryptoBaseUnit: string, buyAmountCryptoBaseUnit: string) => { return getRate({ sellAmountCryptoBaseUnit, @@ -238,107 +110,45 @@ const _getTradeQuote = async ( }) } - const getSwapSource = (swapType: string | undefined, isBoosted: boolean) => { - return swapType === CHAINFLIP_REGULAR_QUOTE - ? isBoosted - ? CHAINFLIP_BOOST_SWAP_SOURCE - : CHAINFLIP_SWAP_SOURCE - : isBoosted - ? CHAINFLIP_DCA_BOOST_SWAP_SOURCE - : CHAINFLIP_DCA_SWAP_SOURCE - } - const quotes: TradeQuote[] = [] - for (const singleQuoteResponse of quoteResponse) { - const isStreaming = singleQuoteResponse.type === CHAINFLIP_DCA_QUOTE - const feeData = await getFeeData() - - if (isStreaming && !deps.config.REACT_APP_FEATURE_CHAINFLIP_DCA) { - // DCA currently disabled - Streaming swap logic is very much tied to THOR currently and will deserve its own PR to generalize - // Even if we manage to get DCA swaps to execute, we wouldn't manage to properly poll with current web THOR-centric arch - continue - } - - if (singleQuoteResponse.boostQuote) { - const boostRate = getQuoteRate( - singleQuoteResponse.boostQuote.ingressAmountNative!, - singleQuoteResponse.boostQuote.egressAmountNative!, - ) + const feeData = await getFeeData() - const boostTradeQuote: TradeQuote = { - id: uuid(), - rate: boostRate, - receiveAddress, - potentialAffiliateBps: commissionBps, - affiliateBps: commissionBps, - isStreaming, - slippageTolerancePercentageDecimal: - input.slippageTolerancePercentageDecimal ?? - getDefaultSlippageDecimalPercentageForSwapper(SwapperName.Chainflip), - steps: [ - { - buyAmountBeforeFeesCryptoBaseUnit: singleQuoteResponse.boostQuote.egressAmountNative!, - buyAmountAfterFeesCryptoBaseUnit: singleQuoteResponse.boostQuote.egressAmountNative!, - sellAmountIncludingProtocolFeesCryptoBaseUnit: - singleQuoteResponse.boostQuote.ingressAmountNative!, - feeData: { - protocolFees: getProtocolFees(singleQuoteResponse.boostQuote), - ...feeData, - }, - rate: boostRate, - source: getSwapSource(singleQuoteResponse.type, true), - buyAsset, - sellAsset, - accountNumber, - allowanceContract: '0x0', // Chainflip does not use contracts - estimatedExecutionTimeMs: - singleQuoteResponse.boostQuote.estimatedDurationSeconds! * 1000, - }, - ], - } - - quotes.push(boostTradeQuote) - } + const rate = getQuoteRate(quoteResponse.inAmount, quoteResponse.outAmount) - const rate = getQuoteRate( - singleQuoteResponse.ingressAmountNative!, - singleQuoteResponse.egressAmountNative!, - ) - - const tradeQuote: TradeQuote = { - id: uuid(), - rate, - receiveAddress, - potentialAffiliateBps: commissionBps, - affiliateBps: commissionBps, - isStreaming, - slippageTolerancePercentageDecimal: - input.slippageTolerancePercentageDecimal ?? - getDefaultSlippageDecimalPercentageForSwapper(SwapperName.Chainflip), - steps: [ - { - buyAmountBeforeFeesCryptoBaseUnit: singleQuoteResponse.egressAmountNative!, - buyAmountAfterFeesCryptoBaseUnit: singleQuoteResponse.egressAmountNative!, - sellAmountIncludingProtocolFeesCryptoBaseUnit: singleQuoteResponse.ingressAmountNative!, - feeData: { - protocolFees: getProtocolFees(singleQuoteResponse), - ...feeData, - }, - rate, - source: getSwapSource(singleQuoteResponse.type, false), - buyAsset, - sellAsset, - accountNumber, - allowanceContract: '0x0', // Chainflip does not use contracts - all Txs are sends - estimatedExecutionTimeMs: singleQuoteResponse.estimatedDurationSeconds! * 1000, + const tradeQuote: TradeQuote = { + id: uuid(), + rate, + receiveAddress, + potentialAffiliateBps: affiliateBps, + affiliateBps, + isStreaming: false, + slippageTolerancePercentageDecimal: + input.slippageTolerancePercentageDecimal ?? + getDefaultSlippageDecimalPercentageForSwapper(SwapperName.Jupiter), + steps: [ + { + buyAmountBeforeFeesCryptoBaseUnit: quoteResponse.outAmount, + buyAmountAfterFeesCryptoBaseUnit: quoteResponse.outAmount, + sellAmountIncludingProtocolFeesCryptoBaseUnit: quoteResponse.inAmount, + feeData: { + // @TODO: calculate fees + protocolFees: {}, + ...feeData, }, - ], - } - - quotes.push(tradeQuote) + rate, + source: SwapperName.Jupiter, + buyAsset, + sellAsset, + accountNumber, + allowanceContract: '0x0', // Chainflip does not use contracts - all Txs are sends + estimatedExecutionTimeMs: quoteResponse.timeTaken! * 1000, + }, + ], } + quotes.push(tradeQuote) + return Ok(quotes) } diff --git a/packages/swapper/src/swappers/JupiterSwapper/utils/constants.ts b/packages/swapper/src/swappers/JupiterSwapper/utils/constants.ts index 8150c0032bb..b6437d50c86 100644 --- a/packages/swapper/src/swappers/JupiterSwapper/utils/constants.ts +++ b/packages/swapper/src/swappers/JupiterSwapper/utils/constants.ts @@ -1,3 +1,11 @@ +import type { ChainId } from '@shapeshiftoss/caip' import { KnownChainIds } from '@shapeshiftoss/types' +import type { SupportedChainIds } from '../../../types' + export const jupiterSupportedChainIds = [KnownChainIds.SolanaMainnet] as const + +export const JUPITER_SUPPORTED_CHAIN_IDS: SupportedChainIds = { + sell: jupiterSupportedChainIds as unknown as ChainId[], + buy: jupiterSupportedChainIds as unknown as ChainId[], +} diff --git a/packages/swapper/src/swappers/JupiterSwapper/utils/helpers.ts b/packages/swapper/src/swappers/JupiterSwapper/utils/helpers.ts index 096d4bd7ae5..3d5eb9b4787 100644 --- a/packages/swapper/src/swappers/JupiterSwapper/utils/helpers.ts +++ b/packages/swapper/src/swappers/JupiterSwapper/utils/helpers.ts @@ -1,21 +1,19 @@ -import { type AssetId, type ChainId } from '@shapeshiftoss/caip' +import type { ChainId } from '@shapeshiftoss/caip' import type { Asset } from '@shapeshiftoss/types' import { bn, bnOrZero, fromBaseUnit } from '@shapeshiftoss/utils' +import type { Result } from '@sniptt/monads' +import type { AxiosResponse } from 'axios' +import type { SwapErrorRight } from '../../../types' +import type { QuoteResponse } from '../models/QuoteResponse' import type { JupiterSupportedChainId } from '../types' import { jupiterSupportedChainIds } from './constants' +import { jupiterService } from './jupiterService' export const isSupportedChainId = (chainId: ChainId): chainId is JupiterSupportedChainId => { return jupiterSupportedChainIds.includes(chainId as JupiterSupportedChainId) } -export const isSupportedAssetId = ( - chainId: ChainId, - assetId: AssetId, -): chainId is JupiterSupportedChainId => { - return jupiterSupportedChainIds[chainId as JupiterSupportedChainId]!.includes(assetId) -} - export const calculateChainflipMinPrice = ({ sellAmountIncludingProtocolFeesCryptoBaseUnit, buyAmountAfterFeesCryptoBaseUnit, @@ -48,3 +46,29 @@ export const calculateChainflipMinPrice = ({ return minimumRate } + +type GetJupiterSwapArgs = { + apiUrl: string + sourceAsset: string + destinationAsset: string + commissionBps: string + amount: string + slippageBps?: string +} + +export const getJupiterSwap = ({ + apiUrl, + sourceAsset, + destinationAsset, + commissionBps, + amount, + slippageBps, +}: GetJupiterSwapArgs): Promise, SwapErrorRight>> => + jupiterService.get( + `${apiUrl}/v6/quote` + + `?inputMint=${sourceAsset}` + + `&outputMint=${destinationAsset}` + + `&amount=${amount}` + + `&slippageBps=${slippageBps}` + + `&platformFeeBps=${commissionBps}`, + ) diff --git a/packages/swapper/src/swappers/JupiterSwapper/utils/jupiterService.ts b/packages/swapper/src/swappers/JupiterSwapper/utils/jupiterService.ts new file mode 100644 index 00000000000..79e7c6057d8 --- /dev/null +++ b/packages/swapper/src/swappers/JupiterSwapper/utils/jupiterService.ts @@ -0,0 +1,20 @@ +import { SwapperName } from '../../../types' +import { createCache, makeSwapperAxiosServiceMonadic } from '../../../utils' + +const maxAge = 15 * 1000 // 15 seconds ttl for all except cached to get fresh status updates +const cachedUrls: string[] = [] + +const axiosConfig = { + timeout: 10000, + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + }, +} + +const jupiterServiceBase = createCache(maxAge, cachedUrls, axiosConfig) + +export const jupiterService = makeSwapperAxiosServiceMonadic( + jupiterServiceBase, + SwapperName.Chainflip, +) diff --git a/packages/swapper/src/types.ts b/packages/swapper/src/types.ts index 662b6a28f17..e0afa4ee302 100644 --- a/packages/swapper/src/types.ts +++ b/packages/swapper/src/types.ts @@ -6,7 +6,7 @@ import type { EvmChainAdapter, UtxoChainAdapter, } from '@shapeshiftoss/chain-adapters' -import type { ChainAdapter as SolanaChainAdapter } from '@shapeshiftoss/chain-adapters/dist/solana/SolanaChainAdapter' +// import type { ChainAdapter as SolanaChainAdapter } from '@shapeshiftoss/chain-adapters/dist/solana/SolanaChainAdapter' import type { BTCSignTx, HDWallet, SolanaSignTx } from '@shapeshiftoss/hdwallet-core' import type { AccountMetadata, @@ -51,6 +51,7 @@ export type SwapperConfig = { REACT_APP_CHAINFLIP_API_KEY: string REACT_APP_CHAINFLIP_API_URL: string REACT_APP_FEATURE_CHAINFLIP_DCA: boolean + REACT_APP_JUPITER_API_URL: string } export enum SwapperName { @@ -62,6 +63,7 @@ export enum SwapperName { ArbitrumBridge = 'Arbitrum Bridge', Portals = 'Portals', Chainflip = 'Chainflip', + Jupiter = 'Jupiter', } export type SwapSource = SwapperName | `${SwapperName} • ${string}` @@ -221,7 +223,7 @@ export type CosmosSdkSwapperDeps = { assertGetCosmosSdkChainAdapter: (chainId: ChainId) => CosmosSdkChainAdapter } export type SolanaSwapperDeps = { - assertGetSolanaChainAdapter: (chainId: ChainId) => SolanaChainAdapter + assertGetSolanaChainAdapter: (chainId: ChainId) => any } export type SwapperDeps = { diff --git a/src/components/MultiHopTrade/components/TradeInput/components/SwapperIcon/SwapperIcon.tsx b/src/components/MultiHopTrade/components/TradeInput/components/SwapperIcon/SwapperIcon.tsx index a9a1a24e72b..a62cdd891b5 100644 --- a/src/components/MultiHopTrade/components/TradeInput/components/SwapperIcon/SwapperIcon.tsx +++ b/src/components/MultiHopTrade/components/TradeInput/components/SwapperIcon/SwapperIcon.tsx @@ -8,6 +8,7 @@ import ZrxIcon from './0x-icon.png' import ArbitrumBridgeIcon from './arbitrum-bridge-icon.png' import ChainflipIcon from './chainflip-icon.png' import CowIcon from './cow-icon.png' +import JupiterIcon from './jupiter-icon.svg' import LiFiIcon from './lifi-icon.png' import PortalsIcon from './portals-icon.png' import THORChainIcon from './thorchain-icon.png' @@ -35,6 +36,8 @@ export const SwapperIcon = ({ return PortalsIcon case SwapperName.Chainflip: return ChainflipIcon + case SwapperName.Jupiter: + return JupiterIcon case SwapperName.Test: return '' default: diff --git a/src/components/MultiHopTrade/components/TradeInput/components/SwapperIcon/jupiter-icon.svg b/src/components/MultiHopTrade/components/TradeInput/components/SwapperIcon/jupiter-icon.svg new file mode 100644 index 00000000000..382f9eadf12 --- /dev/null +++ b/src/components/MultiHopTrade/components/TradeInput/components/SwapperIcon/jupiter-icon.svg @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/config.ts b/src/config.ts index b3eb34a432c..41c5634396f 100644 --- a/src/config.ts +++ b/src/config.ts @@ -180,6 +180,8 @@ const validators = { REACT_APP_CHAINFLIP_API_URL: url(), REACT_APP_FEATURE_PUBLIC_TRADE_ROUTE: bool({ default: false }), REACT_APP_FEATURE_THOR_FREE_FEES: bool({ default: false }), + REACT_APP_FEATURE_JUPITER: bool({ default: false }), + REACT_APP_JUPITER_API_URL: url(), } function reporter({ errors }: envalid.ReporterOptions) { diff --git a/src/state/helpers.ts b/src/state/helpers.ts index 2a77bb7a9f8..b3b0d8d7226 100644 --- a/src/state/helpers.ts +++ b/src/state/helpers.ts @@ -13,6 +13,7 @@ export const isCrossAccountTradeSupported = (swapperName: SwapperName) => { case SwapperName.CowSwap: case SwapperName.ArbitrumBridge: case SwapperName.Portals: + case SwapperName.Jupiter: case SwapperName.Test: // Technically supported for Arbitrum Bridge, but we disable it for the sake of simplicity for now return false @@ -22,7 +23,16 @@ export const isCrossAccountTradeSupported = (swapperName: SwapperName) => { } export const getEnabledSwappers = ( - { Chainflip, Portals, LifiSwap, ThorSwap, ZrxSwap, ArbitrumBridge, Cowswap }: FeatureFlags, + { + Chainflip, + Portals, + LifiSwap, + ThorSwap, + ZrxSwap, + ArbitrumBridge, + Cowswap, + Jupiter, + }: FeatureFlags, isCrossAccountTrade: boolean, ): Record => { return { @@ -41,6 +51,8 @@ export const getEnabledSwappers = ( Portals && (!isCrossAccountTrade || isCrossAccountTradeSupported(SwapperName.Portals)), [SwapperName.Chainflip]: Chainflip && (!isCrossAccountTrade || isCrossAccountTradeSupported(SwapperName.Chainflip)), + [SwapperName.Jupiter]: + Jupiter && (!isCrossAccountTrade || isCrossAccountTradeSupported(SwapperName.Jupiter)), [SwapperName.Test]: false, } } diff --git a/src/state/slices/preferencesSlice/preferencesSlice.ts b/src/state/slices/preferencesSlice/preferencesSlice.ts index 599757e623d..8e500ef2a38 100644 --- a/src/state/slices/preferencesSlice/preferencesSlice.ts +++ b/src/state/slices/preferencesSlice/preferencesSlice.ts @@ -72,6 +72,7 @@ export type FeatureFlags = { ChainflipDca: boolean PublicTradeRoute: boolean ThorFreeFees: boolean + Jupiter: boolean } export type Flag = keyof FeatureFlags @@ -167,6 +168,7 @@ const initialState: Preferences = { ChainflipDca: getConfig().REACT_APP_FEATURE_CHAINFLIP_DCA, PublicTradeRoute: getConfig().REACT_APP_FEATURE_PUBLIC_TRADE_ROUTE, ThorFreeFees: getConfig().REACT_APP_FEATURE_THOR_FREE_FEES, + Jupiter: getConfig().REACT_APP_FEATURE_JUPITER, }, selectedLocale: simpleLocale(), balanceThreshold: '0', diff --git a/src/test/mocks/store.ts b/src/test/mocks/store.ts index c17a5ab431d..fef5ff2cff3 100644 --- a/src/test/mocks/store.ts +++ b/src/test/mocks/store.ts @@ -133,6 +133,7 @@ export const mockStore: ReduxState = { ChainflipDca: false, PublicTradeRoute: false, ThorFreeFees: false, + Jupiter: false, }, selectedLocale: 'en', balanceThreshold: '0', From 54e304d0ce047da8cf7a7c6361a414c10810d684 Mon Sep 17 00:00:00 2001 From: NeOMakinG <14963751+NeOMakinG@users.noreply.github.com> Date: Wed, 13 Nov 2024 15:16:00 +0100 Subject: [PATCH 098/127] fix: remove copy pasta --- .../swapperApi/getTradeQuote.ts | 2 +- .../swappers/JupiterSwapper/utils/helpers.ts | 33 ------------------- .../JupiterSwapper/utils/jupiterService.ts | 2 +- 3 files changed, 2 insertions(+), 35 deletions(-) diff --git a/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeQuote.ts b/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeQuote.ts index 3b53dd527d8..560ecf972eb 100644 --- a/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeQuote.ts +++ b/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeQuote.ts @@ -141,7 +141,7 @@ const _getTradeQuote = async ( buyAsset, sellAsset, accountNumber, - allowanceContract: '0x0', // Chainflip does not use contracts - all Txs are sends + allowanceContract: '0x0', estimatedExecutionTimeMs: quoteResponse.timeTaken! * 1000, }, ], diff --git a/packages/swapper/src/swappers/JupiterSwapper/utils/helpers.ts b/packages/swapper/src/swappers/JupiterSwapper/utils/helpers.ts index 3d5eb9b4787..46b80b71b8d 100644 --- a/packages/swapper/src/swappers/JupiterSwapper/utils/helpers.ts +++ b/packages/swapper/src/swappers/JupiterSwapper/utils/helpers.ts @@ -14,39 +14,6 @@ export const isSupportedChainId = (chainId: ChainId): chainId is JupiterSupporte return jupiterSupportedChainIds.includes(chainId as JupiterSupportedChainId) } -export const calculateChainflipMinPrice = ({ - sellAmountIncludingProtocolFeesCryptoBaseUnit, - buyAmountAfterFeesCryptoBaseUnit, - slippageTolerancePercentageDecimal, - sellAsset, - buyAsset, -}: { - sellAmountIncludingProtocolFeesCryptoBaseUnit: string - buyAmountAfterFeesCryptoBaseUnit: string - slippageTolerancePercentageDecimal: string | undefined - sellAsset: Asset - buyAsset: Asset -}): string => { - const sellAmountCryptoPrecision = fromBaseUnit( - sellAmountIncludingProtocolFeesCryptoBaseUnit, - sellAsset.precision, - ) - - const buyAmountCryptoPrecision = fromBaseUnit( - buyAmountAfterFeesCryptoBaseUnit, - buyAsset.precision, - ) - - const estimatedPrice = bn(buyAmountCryptoPrecision).div(sellAmountCryptoPrecision) - - // This is called minimumPrice upstream but this really is a rate, let's not honour confusing terminology - const minimumRate = estimatedPrice - .times(bn(1).minus(bnOrZero(slippageTolerancePercentageDecimal))) - .toFixed(buyAsset.precision) - - return minimumRate -} - type GetJupiterSwapArgs = { apiUrl: string sourceAsset: string diff --git a/packages/swapper/src/swappers/JupiterSwapper/utils/jupiterService.ts b/packages/swapper/src/swappers/JupiterSwapper/utils/jupiterService.ts index 79e7c6057d8..f4b2102b3e5 100644 --- a/packages/swapper/src/swappers/JupiterSwapper/utils/jupiterService.ts +++ b/packages/swapper/src/swappers/JupiterSwapper/utils/jupiterService.ts @@ -16,5 +16,5 @@ const jupiterServiceBase = createCache(maxAge, cachedUrls, axiosConfig) export const jupiterService = makeSwapperAxiosServiceMonadic( jupiterServiceBase, - SwapperName.Chainflip, + SwapperName.Jupiter, ) From 84b12de03856b1c5df93334d18c677995419a04c Mon Sep 17 00:00:00 2001 From: NeOMakinG <14963751+NeOMakinG@users.noreply.github.com> Date: Wed, 13 Nov 2024 16:06:21 +0100 Subject: [PATCH 099/127] fix: refactor --- packages/chain-adapters/src/solana/SolanaChainAdapter.ts | 8 +------- packages/chain-adapters/src/utils/index.ts | 1 + packages/chain-adapters/src/utils/solanaUtils.ts | 9 +++++++++ .../swapper/src/swappers/JupiterSwapper/utils/helpers.ts | 2 -- .../filterBuyAssetsBySellAssetId.ts | 3 +-- 5 files changed, 12 insertions(+), 11 deletions(-) create mode 100644 packages/chain-adapters/src/utils/solanaUtils.ts diff --git a/packages/chain-adapters/src/solana/SolanaChainAdapter.ts b/packages/chain-adapters/src/solana/SolanaChainAdapter.ts index 49190da3c72..f5faf8b411e 100644 --- a/packages/chain-adapters/src/solana/SolanaChainAdapter.ts +++ b/packages/chain-adapters/src/solana/SolanaChainAdapter.ts @@ -8,7 +8,7 @@ import { } from '@shapeshiftoss/caip' import type { SolanaSignTx, SolanaTxInstruction } from '@shapeshiftoss/hdwallet-core' import { supportsSolana } from '@shapeshiftoss/hdwallet-core' -import type { BIP44Params, SolanaChainId } from '@shapeshiftoss/types' +import type { BIP44Params } from '@shapeshiftoss/types' import { KnownChainIds } from '@shapeshiftoss/types' import * as unchained from '@shapeshiftoss/unchained-client' import { BigNumber, bn } from '@shapeshiftoss/utils' @@ -59,12 +59,6 @@ import { microLamportsToLamports } from './utils' export const solanaChainIds = [KnownChainIds.SolanaMainnet] as const -export const isSolanaChainId = ( - maybeSolanaChainId: string | SolanaChainId, -): maybeSolanaChainId is SolanaChainId => { - return solanaChainIds.includes(maybeSolanaChainId as SolanaChainId) -} - // Maximum compute units allowed for a single solana transaction const MAX_COMPUTE_UNITS = 1400000 diff --git a/packages/chain-adapters/src/utils/index.ts b/packages/chain-adapters/src/utils/index.ts index cacfec3cd12..edb9a532ea1 100644 --- a/packages/chain-adapters/src/utils/index.ts +++ b/packages/chain-adapters/src/utils/index.ts @@ -5,6 +5,7 @@ export * from './bignumber' export * from './bip44' export * from './fees' export * from './utxoUtils' +export * from './solanaUtils' export * from './ledgerAppGate' export const getAssetNamespace = (type: string): AssetNamespace => { diff --git a/packages/chain-adapters/src/utils/solanaUtils.ts b/packages/chain-adapters/src/utils/solanaUtils.ts new file mode 100644 index 00000000000..b2fd2ecde01 --- /dev/null +++ b/packages/chain-adapters/src/utils/solanaUtils.ts @@ -0,0 +1,9 @@ +import type { SolanaChainId } from '@shapeshiftoss/types' + +import { solanaChainIds } from '../solana/SolanaChainAdapter' + +export const isSolanaChainId = ( + maybeSolanaChainId: string | SolanaChainId, +): maybeSolanaChainId is SolanaChainId => { + return solanaChainIds.includes(maybeSolanaChainId as SolanaChainId) +} diff --git a/packages/swapper/src/swappers/JupiterSwapper/utils/helpers.ts b/packages/swapper/src/swappers/JupiterSwapper/utils/helpers.ts index 46b80b71b8d..15525a05c18 100644 --- a/packages/swapper/src/swappers/JupiterSwapper/utils/helpers.ts +++ b/packages/swapper/src/swappers/JupiterSwapper/utils/helpers.ts @@ -1,6 +1,4 @@ import type { ChainId } from '@shapeshiftoss/caip' -import type { Asset } from '@shapeshiftoss/types' -import { bn, bnOrZero, fromBaseUnit } from '@shapeshiftoss/utils' import type { Result } from '@sniptt/monads' import type { AxiosResponse } from 'axios' diff --git a/packages/swapper/src/swappers/utils/filterBuyAssetsBySellAssetId/filterBuyAssetsBySellAssetId.ts b/packages/swapper/src/swappers/utils/filterBuyAssetsBySellAssetId/filterBuyAssetsBySellAssetId.ts index 4c3572a2311..5dfd0df7be0 100644 --- a/packages/swapper/src/swappers/utils/filterBuyAssetsBySellAssetId/filterBuyAssetsBySellAssetId.ts +++ b/packages/swapper/src/swappers/utils/filterBuyAssetsBySellAssetId/filterBuyAssetsBySellAssetId.ts @@ -1,6 +1,5 @@ import { arbitrumNovaChainId, type ChainId } from '@shapeshiftoss/caip' -import { isEvmChainId } from '@shapeshiftoss/chain-adapters' -import { isSolanaChainId } from '@shapeshiftoss/chain-adapters/src/solana/SolanaChainAdapter' +import { isEvmChainId, isSolanaChainId } from '@shapeshiftoss/chain-adapters' import type { Asset } from '@shapeshiftoss/types' import type { BuyAssetBySellIdInput } from '../../../types' From 85b771eb450eaa7f1dca369d0ec6daeb0ac904a5 Mon Sep 17 00:00:00 2001 From: NeOMakinG <14963751+NeOMakinG@users.noreply.github.com> Date: Wed, 13 Nov 2024 16:09:47 +0100 Subject: [PATCH 100/127] fix: refactor --- packages/swapper/src/types.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/swapper/src/types.ts b/packages/swapper/src/types.ts index e0afa4ee302..e2fd31264d4 100644 --- a/packages/swapper/src/types.ts +++ b/packages/swapper/src/types.ts @@ -6,7 +6,7 @@ import type { EvmChainAdapter, UtxoChainAdapter, } from '@shapeshiftoss/chain-adapters' -// import type { ChainAdapter as SolanaChainAdapter } from '@shapeshiftoss/chain-adapters/dist/solana/SolanaChainAdapter' +import type { ChainAdapter as SolanaChainAdapter } from '@shapeshiftoss/chain-adapters/dist/solana/SolanaChainAdapter' import type { BTCSignTx, HDWallet, SolanaSignTx } from '@shapeshiftoss/hdwallet-core' import type { AccountMetadata, @@ -223,7 +223,7 @@ export type CosmosSdkSwapperDeps = { assertGetCosmosSdkChainAdapter: (chainId: ChainId) => CosmosSdkChainAdapter } export type SolanaSwapperDeps = { - assertGetSolanaChainAdapter: (chainId: ChainId) => any + assertGetSolanaChainAdapter: (chainId: ChainId) => SolanaChainAdapter } export type SwapperDeps = { From ef0066577e05bda0b438ad4ba4b75bfe9dfe78ea Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Thu, 14 Nov 2024 09:53:46 +0700 Subject: [PATCH 101/127] fix: solana token sends to PDAs --- packages/chain-adapters/src/solana/SolanaChainAdapter.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/chain-adapters/src/solana/SolanaChainAdapter.ts b/packages/chain-adapters/src/solana/SolanaChainAdapter.ts index 279d456b9c0..ef28b3675f8 100644 --- a/packages/chain-adapters/src/solana/SolanaChainAdapter.ts +++ b/packages/chain-adapters/src/solana/SolanaChainAdapter.ts @@ -466,6 +466,7 @@ export class ChainAdapter implements IChainAdapter const destinationTokenAccount = getAssociatedTokenAddressSync( new PublicKey(tokenId), new PublicKey(to), + true, ) // check if destination token account exists and add creation instruction if it doesn't @@ -490,7 +491,7 @@ export class ChainAdapter implements IChainAdapter instructions.push( createTransferInstruction( - getAssociatedTokenAddressSync(new PublicKey(tokenId), new PublicKey(from)), + getAssociatedTokenAddressSync(new PublicKey(tokenId), new PublicKey(from), true), destinationTokenAccount, new PublicKey(from), Number(value), From 8b1e16276805c69c0b7aaf7e6f9c3373dcfd0d83 Mon Sep 17 00:00:00 2001 From: NeOMakinG <14963751+NeOMakinG@users.noreply.github.com> Date: Fri, 15 Nov 2024 09:18:05 +0100 Subject: [PATCH 102/127] fix: continue --- .../src/swappers/JupiterSwapper/endpoints.ts | 82 ++++++++++--- .../JupiterSwapper/models/AccountMeta.ts | 84 +++++++++++++ .../JupiterSwapper/models/Instruction.ts | 91 ++++++++++++++ .../models/SwapInstructionsResponse.ts | 116 ++++++++++++++++++ .../swapperApi/getTradeQuote.ts | 54 ++++++-- .../swappers/JupiterSwapper/utils/helpers.ts | 39 ++++-- packages/swapper/src/types.ts | 1 + react-app-rewired/headers/csps/jupiter.ts | 5 + .../useGetTradeQuotes/useGetTradeQuotes.tsx | 1 + 9 files changed, 443 insertions(+), 30 deletions(-) create mode 100644 packages/swapper/src/swappers/JupiterSwapper/models/AccountMeta.ts create mode 100644 packages/swapper/src/swappers/JupiterSwapper/models/Instruction.ts create mode 100644 packages/swapper/src/swappers/JupiterSwapper/models/SwapInstructionsResponse.ts create mode 100644 react-app-rewired/headers/csps/jupiter.ts diff --git a/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts b/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts index 926987c9dfe..667aaa12fd7 100644 --- a/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts +++ b/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts @@ -1,34 +1,84 @@ -import { fromChainId } from '@shapeshiftoss/caip' +import type { BuildSendApiTxInput } from '@shapeshiftoss/chain-adapters' import type { SolanaSignTx } from '@shapeshiftoss/hdwallet-core' +import type { KnownChainIds } from '@shapeshiftoss/types' import { TxStatus } from '@shapeshiftoss/unchained-client' +import type { AxiosError } from 'axios' import type { InterpolationOptions } from 'node-polyglot' import type { GetUnsignedSolanaTransactionArgs } from '../../types' import { type SwapperApi } from '../../types' -import { isExecutableTradeQuote } from '../../utils' +import { isExecutableTradeQuote, isExecutableTradeStep } from '../../utils' import { getTradeQuote, getTradeRate } from './swapperApi/getTradeQuote' +import { getJupiterSwapInstructions } from './utils/helpers' export const jupiterApi: SwapperApi = { getTradeQuote, getTradeRate, - getUnsignedSolanaTransaction: ({ - chainId, - from, + getUnsignedSolanaTransaction: async ({ tradeQuote, + from, + assertGetSolanaChainAdapter, + config, }: GetUnsignedSolanaTransactionArgs): Promise => { - if (!isExecutableTradeQuote(tradeQuote)) throw new Error('Unable to execute trade') + if (!isExecutableTradeQuote(tradeQuote)) throw Error('Unable to execute trade') + + const jupiterUrl = config.REACT_APP_JUPITER_API_URL + + const step = tradeQuote.steps[0] + + if (!isExecutableTradeStep(step)) throw Error('Unable to execute step') + + if (!tradeQuote.rawQuote) throw Error('Missing raw quote') + + // @TODO: add feeAccount + const maybeSwapResponse = await getJupiterSwapInstructions({ + apiUrl: jupiterUrl, + fromAddress: from, + rawQuote: tradeQuote.rawQuote, + }) + + if (maybeSwapResponse.isErr()) { + const error = maybeSwapResponse.unwrapErr() + const cause = error.cause as AxiosError + throw Error(cause.response!.data.detail) + } - return { - to: '', + const { data: swapResponse } = maybeSwapResponse.unwrap() + + const computeBudgetInstructions = swapResponse.computeBudgetInstructions.map(instruction => { + return { + ...instruction, + keys: instruction.accounts, + data: Buffer.from(instruction.data, 'base64'), + } + }) + + const setupInstructions = swapResponse.setupInstructions.map(instruction => { + return { + ...instruction, + keys: instruction.accounts, + data: Buffer.from(instruction.data, 'base64'), + } + }) + + const swapInstruction = { + ...swapResponse.swapInstruction, + keys: swapResponse.swapInstruction.accounts, + data: Buffer.from(swapResponse.swapInstruction.data, 'base64'), + } + + const adapter = assertGetSolanaChainAdapter(step.sellAsset.chainId) + + const buildSwapTxInput: BuildSendApiTxInput = { from, - value: '', - data: '', - chainId: Number(fromChainId(chainId).chainReference), - // Use the higher amount of the node or the API, as the node doesn't always provide enough gas padding for - // total gas used. - gasLimit: '1', - // @TODO: remove this - } as unknown as Promise + value: step.sellAmountIncludingProtocolFeesCryptoBaseUnit, + accountNumber: step.accountNumber, + chainSpecific: { + instructions: [...computeBudgetInstructions, ...setupInstructions, swapInstruction], + }, + } as unknown as BuildSendApiTxInput + + return (await adapter.buildSendApiTransaction(buildSwapTxInput)).txToSign }, checkTradeStatus: (): Promise<{ diff --git a/packages/swapper/src/swappers/JupiterSwapper/models/AccountMeta.ts b/packages/swapper/src/swappers/JupiterSwapper/models/AccountMeta.ts new file mode 100644 index 00000000000..7e485cf0429 --- /dev/null +++ b/packages/swapper/src/swappers/JupiterSwapper/models/AccountMeta.ts @@ -0,0 +1,84 @@ +// @ts-nocheck +/* tslint:disable */ +/* eslint-disable */ +/** + * Jupiter API v6 + * The core of [jup.ag](https://jup.ag). Easily get a quote and swap through Jupiter API. ### Rate Limit We update our rate limit from time to time depending on the load of our servers. We recommend running your own instance of the API if you want to have high rate limit, here to learn how to run the [self-hosted API](https://station.jup.ag/docs/apis/self-hosted). ### API Wrapper - Typescript [@jup-ag/api](https://github.com/jup-ag/jupiter-quote-api-node) ### Data types - Public keys are base58 encoded strings - raw data such as Vec are base64 encoded strings + * + * The version of the OpenAPI document: 6.0.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +/** + * + * @export + * @interface AccountMeta + */ +export interface AccountMeta { + /** + * + * @type {string} + * @memberof AccountMeta + */ + pubkey: string; + /** + * + * @type {boolean} + * @memberof AccountMeta + */ + isSigner: boolean; + /** + * + * @type {boolean} + * @memberof AccountMeta + */ + isWritable: boolean; +} + +/** + * Check if a given object implements the AccountMeta interface. + */ +export function instanceOfAccountMeta(value: object): boolean { + let isInstance = true; + isInstance = isInstance && "pubkey" in value; + isInstance = isInstance && "isSigner" in value; + isInstance = isInstance && "isWritable" in value; + + return isInstance; +} + +export function AccountMetaFromJSON(json: any): AccountMeta { + return AccountMetaFromJSONTyped(json, false); +} + +export function AccountMetaFromJSONTyped(json: any, ignoreDiscriminator: boolean): AccountMeta { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'pubkey': json['pubkey'], + 'isSigner': json['isSigner'], + 'isWritable': json['isWritable'], + }; +} + +export function AccountMetaToJSON(value?: AccountMeta | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'pubkey': value.pubkey, + 'isSigner': value.isSigner, + 'isWritable': value.isWritable, + }; +} diff --git a/packages/swapper/src/swappers/JupiterSwapper/models/Instruction.ts b/packages/swapper/src/swappers/JupiterSwapper/models/Instruction.ts new file mode 100644 index 00000000000..e1004f3e604 --- /dev/null +++ b/packages/swapper/src/swappers/JupiterSwapper/models/Instruction.ts @@ -0,0 +1,91 @@ +// @ts-nocheck +/* tslint:disable */ +/* eslint-disable */ +/** + * Jupiter API v6 + * The core of [jup.ag](https://jup.ag). Easily get a quote and swap through Jupiter API. ### Rate Limit We update our rate limit from time to time depending on the load of our servers. We recommend running your own instance of the API if you want to have high rate limit, here to learn how to run the [self-hosted API](https://station.jup.ag/docs/apis/self-hosted). ### API Wrapper - Typescript [@jup-ag/api](https://github.com/jup-ag/jupiter-quote-api-node) ### Data types - Public keys are base58 encoded strings - raw data such as Vec are base64 encoded strings + * + * The version of the OpenAPI document: 6.0.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +import type { AccountMeta } from './AccountMeta'; +import { + AccountMetaFromJSON, + AccountMetaFromJSONTyped, + AccountMetaToJSON, +} from './AccountMeta'; + +/** + * + * @export + * @interface Instruction + */ +export interface Instruction { + /** + * + * @type {string} + * @memberof Instruction + */ + programId: string; + /** + * + * @type {Array} + * @memberof Instruction + */ + accounts: Array; + /** + * + * @type {string} + * @memberof Instruction + */ + data: string; +} + +/** + * Check if a given object implements the Instruction interface. + */ +export function instanceOfInstruction(value: object): boolean { + let isInstance = true; + isInstance = isInstance && "programId" in value; + isInstance = isInstance && "accounts" in value; + isInstance = isInstance && "data" in value; + + return isInstance; +} + +export function InstructionFromJSON(json: any): Instruction { + return InstructionFromJSONTyped(json, false); +} + +export function InstructionFromJSONTyped(json: any, ignoreDiscriminator: boolean): Instruction { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'programId': json['programId'], + 'accounts': ((json['accounts'] as Array).map(AccountMetaFromJSON)), + 'data': json['data'], + }; +} + +export function InstructionToJSON(value?: Instruction | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'programId': value.programId, + 'accounts': ((value.accounts as Array).map(AccountMetaToJSON)), + 'data': value.data, + }; +} diff --git a/packages/swapper/src/swappers/JupiterSwapper/models/SwapInstructionsResponse.ts b/packages/swapper/src/swappers/JupiterSwapper/models/SwapInstructionsResponse.ts new file mode 100644 index 00000000000..e844dff146b --- /dev/null +++ b/packages/swapper/src/swappers/JupiterSwapper/models/SwapInstructionsResponse.ts @@ -0,0 +1,116 @@ +// @ts-nocheck +/* tslint:disable */ +/* eslint-disable */ +/** + * Jupiter API v6 + * The core of [jup.ag](https://jup.ag). Easily get a quote and swap through Jupiter API. ### Rate Limit We update our rate limit from time to time depending on the load of our servers. We recommend running your own instance of the API if you want to have high rate limit, here to learn how to run the [self-hosted API](https://station.jup.ag/docs/apis/self-hosted). ### API Wrapper - Typescript [@jup-ag/api](https://github.com/jup-ag/jupiter-quote-api-node) ### Data types - Public keys are base58 encoded strings - raw data such as Vec are base64 encoded strings + * + * The version of the OpenAPI document: 6.0.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +import type { Instruction } from './Instruction'; +import { + InstructionFromJSON, + InstructionFromJSONTyped, + InstructionToJSON, +} from './Instruction'; + +/** + * + * @export + * @interface SwapInstructionsResponse + */ +export interface SwapInstructionsResponse { + /** + * + * @type {Instruction} + * @memberof SwapInstructionsResponse + */ + tokenLedgerInstruction?: Instruction; + /** + * The necessary instructions to setup the compute budget. + * @type {Array} + * @memberof SwapInstructionsResponse + */ + computeBudgetInstructions: Array; + /** + * Setup missing ATA for the users. + * @type {Array} + * @memberof SwapInstructionsResponse + */ + setupInstructions: Array; + /** + * + * @type {Instruction} + * @memberof SwapInstructionsResponse + */ + swapInstruction: Instruction; + /** + * + * @type {Instruction} + * @memberof SwapInstructionsResponse + */ + cleanupInstruction?: Instruction; + /** + * The lookup table addresses that you can use if you are using versioned transaction. + * @type {Array} + * @memberof SwapInstructionsResponse + */ + addressLookupTableAddresses: Array; +} + +/** + * Check if a given object implements the SwapInstructionsResponse interface. + */ +export function instanceOfSwapInstructionsResponse(value: object): boolean { + let isInstance = true; + isInstance = isInstance && "computeBudgetInstructions" in value; + isInstance = isInstance && "setupInstructions" in value; + isInstance = isInstance && "swapInstruction" in value; + isInstance = isInstance && "addressLookupTableAddresses" in value; + + return isInstance; +} + +export function SwapInstructionsResponseFromJSON(json: any): SwapInstructionsResponse { + return SwapInstructionsResponseFromJSONTyped(json, false); +} + +export function SwapInstructionsResponseFromJSONTyped(json: any, ignoreDiscriminator: boolean): SwapInstructionsResponse { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'tokenLedgerInstruction': !exists(json, 'tokenLedgerInstruction') ? undefined : InstructionFromJSON(json['tokenLedgerInstruction']), + 'computeBudgetInstructions': ((json['computeBudgetInstructions'] as Array).map(InstructionFromJSON)), + 'setupInstructions': ((json['setupInstructions'] as Array).map(InstructionFromJSON)), + 'swapInstruction': InstructionFromJSON(json['swapInstruction']), + 'cleanupInstruction': !exists(json, 'cleanupInstruction') ? undefined : InstructionFromJSON(json['cleanupInstruction']), + 'addressLookupTableAddresses': json['addressLookupTableAddresses'], + }; +} + +export function SwapInstructionsResponseToJSON(value?: SwapInstructionsResponse | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'tokenLedgerInstruction': InstructionToJSON(value.tokenLedgerInstruction), + 'computeBudgetInstructions': ((value.computeBudgetInstructions as Array).map(InstructionToJSON)), + 'setupInstructions': ((value.setupInstructions as Array).map(InstructionToJSON)), + 'swapInstruction': InstructionToJSON(value.swapInstruction), + 'cleanupInstruction': InstructionToJSON(value.cleanupInstruction), + 'addressLookupTableAddresses': value.addressLookupTableAddresses, + }; +} diff --git a/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeQuote.ts b/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeQuote.ts index 560ecf972eb..81879dd8e2a 100644 --- a/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeQuote.ts +++ b/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeQuote.ts @@ -1,6 +1,15 @@ -import { CHAIN_NAMESPACE, fromAssetId, solAssetId } from '@shapeshiftoss/caip' +import type { AssetId } from '@shapeshiftoss/caip' +import { + ASSET_NAMESPACE, + CHAIN_NAMESPACE, + CHAIN_REFERENCE, + fromAssetId, + solAssetId, + toAssetId, +} from '@shapeshiftoss/caip' import type { GetFeeDataInput } from '@shapeshiftoss/chain-adapters' import type { KnownChainIds } from '@shapeshiftoss/types' +import { bnOrZero, convertDecimalPercentageToBasisPoints } from '@shapeshiftoss/utils' import type { Result } from '@sniptt/monads' import { Err, Ok } from '@sniptt/monads' import { v4 as uuid } from 'uuid' @@ -9,6 +18,7 @@ import { getDefaultSlippageDecimalPercentageForSwapper } from '../../../constant import type { CommonTradeQuoteInput, GetTradeRateInput, + ProtocolFee, SwapErrorRight, SwapperDeps, TradeQuote, @@ -16,7 +26,7 @@ import type { } from '../../../types' import { SwapperName, TradeQuoteError } from '../../../types' import { getRate, makeSwapErrorRight } from '../../../utils' -import { getJupiterSwap, isSupportedChainId } from '../utils/helpers' +import { getJupiterQuote, isSupportedChainId } from '../utils/helpers' const _getTradeQuote = async ( input: CommonTradeQuoteInput, @@ -32,6 +42,8 @@ const _getTradeQuote = async ( slippageTolerancePercentageDecimal, } = input + const { assetsById } = deps + const jupiterUrl = deps.config.REACT_APP_JUPITER_API_URL if (!isSupportedChainId(sellAsset.chainId)) { @@ -54,13 +66,16 @@ const _getTradeQuote = async ( ) } - const maybeQuoteResponse = await getJupiterSwap({ + const maybeQuoteResponse = await getJupiterQuote({ apiUrl: jupiterUrl, sourceAsset: sellAsset.assetId, destinationAsset: buyAsset.assetId, commissionBps: affiliateBps, amount: sellAmount, - slippageBps: slippageTolerancePercentageDecimal, + slippageBps: convertDecimalPercentageToBasisPoints( + slippageTolerancePercentageDecimal ?? + getDefaultSlippageDecimalPercentageForSwapper(SwapperName.Jupiter), + ).toFixed(), }) if (maybeQuoteResponse.isErr()) { @@ -101,6 +116,31 @@ const _getTradeQuote = async ( } } + const protocolFees: Record = quoteResponse.routePlan.reduce( + (acc, route) => { + const feeAssetId = toAssetId({ + assetReference: route.swapInfo.feeMint, + assetNamespace: ASSET_NAMESPACE.splToken, + chainNamespace: CHAIN_NAMESPACE.Solana, + chainReference: CHAIN_REFERENCE.SolanaMainnet, + }) + const feeAsset = assetsById[feeAssetId] + + // If we can't find the feeAsset, we can't provide a protocol fee to display + // But these fees exists at protocol level, it's mostly to make TS happy as we should have the market data and assets + if (!feeAsset) return acc + + acc[feeAssetId] = { + requiresBalance: false, + amountCryptoBaseUnit: bnOrZero(route.swapInfo.feeAmount).toString(), + asset: feeAsset, + } + + return acc + }, + {} as Record, + ) + const getQuoteRate = (sellAmountCryptoBaseUnit: string, buyAmountCryptoBaseUnit: string) => { return getRate({ sellAmountCryptoBaseUnit, @@ -123,8 +163,9 @@ const _getTradeQuote = async ( potentialAffiliateBps: affiliateBps, affiliateBps, isStreaming: false, + rawQuote: quoteResponse, slippageTolerancePercentageDecimal: - input.slippageTolerancePercentageDecimal ?? + slippageTolerancePercentageDecimal ?? getDefaultSlippageDecimalPercentageForSwapper(SwapperName.Jupiter), steps: [ { @@ -132,8 +173,7 @@ const _getTradeQuote = async ( buyAmountAfterFeesCryptoBaseUnit: quoteResponse.outAmount, sellAmountIncludingProtocolFeesCryptoBaseUnit: quoteResponse.inAmount, feeData: { - // @TODO: calculate fees - protocolFees: {}, + protocolFees, ...feeData, }, rate, diff --git a/packages/swapper/src/swappers/JupiterSwapper/utils/helpers.ts b/packages/swapper/src/swappers/JupiterSwapper/utils/helpers.ts index 15525a05c18..d36e8b64944 100644 --- a/packages/swapper/src/swappers/JupiterSwapper/utils/helpers.ts +++ b/packages/swapper/src/swappers/JupiterSwapper/utils/helpers.ts @@ -1,9 +1,10 @@ -import type { ChainId } from '@shapeshiftoss/caip' +import { type ChainId, fromAssetId } from '@shapeshiftoss/caip' import type { Result } from '@sniptt/monads' import type { AxiosResponse } from 'axios' import type { SwapErrorRight } from '../../../types' import type { QuoteResponse } from '../models/QuoteResponse' +import type { SwapInstructionsResponse } from '../models/SwapInstructionsResponse' import type { JupiterSupportedChainId } from '../types' import { jupiterSupportedChainIds } from './constants' import { jupiterService } from './jupiterService' @@ -12,7 +13,7 @@ export const isSupportedChainId = (chainId: ChainId): chainId is JupiterSupporte return jupiterSupportedChainIds.includes(chainId as JupiterSupportedChainId) } -type GetJupiterSwapArgs = { +type GetJupiterQuoteArgs = { apiUrl: string sourceAsset: string destinationAsset: string @@ -21,19 +22,43 @@ type GetJupiterSwapArgs = { slippageBps?: string } -export const getJupiterSwap = ({ +type GetJupiterSwapArgs = { + apiUrl: string + fromAddress: string + // @TODO: make this mandatory when we have the DAO fee account + feeAccount?: string + rawQuote: unknown +} + +export const getJupiterQuote = ({ apiUrl, sourceAsset, destinationAsset, commissionBps, amount, slippageBps, -}: GetJupiterSwapArgs): Promise, SwapErrorRight>> => +}: GetJupiterQuoteArgs): Promise, SwapErrorRight>> => jupiterService.get( - `${apiUrl}/v6/quote` + - `?inputMint=${sourceAsset}` + - `&outputMint=${destinationAsset}` + + `${apiUrl}/quote` + + `?inputMint=${fromAssetId(sourceAsset).assetReference}` + + `&outputMint=${fromAssetId(destinationAsset).assetReference}` + `&amount=${amount}` + `&slippageBps=${slippageBps}` + `&platformFeeBps=${commissionBps}`, ) + +export const getJupiterSwapInstructions = ({ + apiUrl, + fromAddress, + feeAccount, + rawQuote, +}: GetJupiterSwapArgs): Promise< + Result, SwapErrorRight> +> => + jupiterService.post(`${apiUrl}/swap-instructions`, { + userPublicKey: fromAddress, + feeAccount, + quoteResponse: rawQuote, + dynamicComputeUnitLimit: true, + prioritizationFeeLamports: 'auto', + }) diff --git a/packages/swapper/src/types.ts b/packages/swapper/src/types.ts index e2fd31264d4..fbd381c4e8f 100644 --- a/packages/swapper/src/types.ts +++ b/packages/swapper/src/types.ts @@ -267,6 +267,7 @@ type TradeQuoteBase = { isStreaming?: boolean slippageTolerancePercentageDecimal: string | undefined // undefined if slippage limit is not provided or specified by the swapper isLongtail?: boolean + rawQuote?: unknown } type TradeRateBase = Omit & { receiveAddress: undefined } diff --git a/react-app-rewired/headers/csps/jupiter.ts b/react-app-rewired/headers/csps/jupiter.ts new file mode 100644 index 00000000000..a7947c636be --- /dev/null +++ b/react-app-rewired/headers/csps/jupiter.ts @@ -0,0 +1,5 @@ +import type { Csp } from '../types' + +export const csp: Csp = { + 'connect-src': ['https://quote-api.jup.ag/'], +} diff --git a/src/components/MultiHopTrade/hooks/useGetTradeQuotes/useGetTradeQuotes.tsx b/src/components/MultiHopTrade/hooks/useGetTradeQuotes/useGetTradeQuotes.tsx index ce3f4dea4d1..8c958e7e8c4 100644 --- a/src/components/MultiHopTrade/hooks/useGetTradeQuotes/useGetTradeQuotes.tsx +++ b/src/components/MultiHopTrade/hooks/useGetTradeQuotes/useGetTradeQuotes.tsx @@ -294,6 +294,7 @@ export const useGetTradeQuotes = () => { useGetSwapperTradeQuote(getTradeQuoteArgs(SwapperName.Thorchain)) useGetSwapperTradeQuote(getTradeQuoteArgs(SwapperName.Zrx)) useGetSwapperTradeQuote(getTradeQuoteArgs(SwapperName.Chainflip)) + useGetSwapperTradeQuote(getTradeQuoteArgs(SwapperName.Jupiter)) // true if any debounce, input or swapper is fetching const isAnyTradeQuoteLoading = useAppSelector(selectIsAnyTradeQuoteLoading) From dc473d2daccf0c80522764b78a99a28770c9733c Mon Sep 17 00:00:00 2001 From: NeOMakinG <14963751+NeOMakinG@users.noreply.github.com> Date: Fri, 15 Nov 2024 17:46:59 +0100 Subject: [PATCH 103/127] fix: continue --- packages/caip/src/constants.ts | 2 + .../src/solana/SolanaChainAdapter.ts | 10 +++++ .../src/swappers/JupiterSwapper/endpoints.ts | 39 +++-------------- .../swapperApi/getTradeQuote.ts | 5 ++- .../swappers/JupiterSwapper/utils/helpers.ts | 7 ++- packages/swapper/src/types.ts | 3 +- packages/swapper/src/utils.ts | 43 ++++++++++++++++++- src/lib/tradeExecution.ts | 1 + 8 files changed, 68 insertions(+), 42 deletions(-) diff --git a/packages/caip/src/constants.ts b/packages/caip/src/constants.ts index 6ea029a0147..5e0f705bda7 100644 --- a/packages/caip/src/constants.ts +++ b/packages/caip/src/constants.ts @@ -16,6 +16,8 @@ export const arbitrumAssetId: AssetId = 'eip155:42161/slip44:60' export const arbitrumNovaAssetId: AssetId = 'eip155:42170/slip44:60' export const baseAssetId: AssetId = 'eip155:8453/slip44:60' export const solAssetId: AssetId = 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/slip44:501' +export const wrappedSolAssetId: AssetId = + 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/token:So11111111111111111111111111111111111111112' export const foxatarAssetId: AssetId = 'eip155:137/erc721:0x2e727c425a11ce6b8819b3004db332c12d2af2a2' diff --git a/packages/chain-adapters/src/solana/SolanaChainAdapter.ts b/packages/chain-adapters/src/solana/SolanaChainAdapter.ts index 812f688d0f8..a28c666b62f 100644 --- a/packages/chain-adapters/src/solana/SolanaChainAdapter.ts +++ b/packages/chain-adapters/src/solana/SolanaChainAdapter.ts @@ -515,6 +515,12 @@ export class ChainAdapter implements IChainAdapter } } + public async getTxStatus(tx: unchained.solana.Tx, pubkey: string): Promise { + const parsedTx = await this.parseTx(tx, pubkey) + + return parsedTx.status + } + private async parseTx(tx: unchained.solana.Tx, pubkey: string): Promise { const { address: _, ...parsedTx } = await this.parser.parse(tx, pubkey) @@ -530,4 +536,8 @@ export class ChainAdapter implements IChainAdapter })), } } + + get httpProvider(): unchained.solana.Api { + return this.providers.http + } } diff --git a/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts b/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts index 667aaa12fd7..88a1f6d85f7 100644 --- a/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts +++ b/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts @@ -1,13 +1,11 @@ import type { BuildSendApiTxInput } from '@shapeshiftoss/chain-adapters' import type { SolanaSignTx } from '@shapeshiftoss/hdwallet-core' import type { KnownChainIds } from '@shapeshiftoss/types' -import { TxStatus } from '@shapeshiftoss/unchained-client' import type { AxiosError } from 'axios' -import type { InterpolationOptions } from 'node-polyglot' import type { GetUnsignedSolanaTransactionArgs } from '../../types' import { type SwapperApi } from '../../types' -import { isExecutableTradeQuote, isExecutableTradeStep } from '../../utils' +import { checkSolanaSwapStatus, isExecutableTradeQuote, isExecutableTradeStep } from '../../utils' import { getTradeQuote, getTradeRate } from './swapperApi/getTradeQuote' import { getJupiterSwapInstructions } from './utils/helpers' @@ -30,7 +28,6 @@ export const jupiterApi: SwapperApi = { if (!tradeQuote.rawQuote) throw Error('Missing raw quote') - // @TODO: add feeAccount const maybeSwapResponse = await getJupiterSwapInstructions({ apiUrl: jupiterUrl, fromAddress: from, @@ -70,43 +67,17 @@ export const jupiterApi: SwapperApi = { const adapter = assertGetSolanaChainAdapter(step.sellAsset.chainId) const buildSwapTxInput: BuildSendApiTxInput = { + to: '', from, - value: step.sellAmountIncludingProtocolFeesCryptoBaseUnit, + value: '0', accountNumber: step.accountNumber, chainSpecific: { instructions: [...computeBudgetInstructions, ...setupInstructions, swapInstruction], }, - } as unknown as BuildSendApiTxInput + } return (await adapter.buildSendApiTransaction(buildSwapTxInput)).txToSign }, - checkTradeStatus: (): Promise<{ - status: TxStatus - buyTxHash: string | undefined - message: string | [string, InterpolationOptions] | undefined - }> => { - try { - return { - buyTxHash: '', - status: TxStatus.Pending, - message: '', - } as unknown as Promise<{ - status: TxStatus - buyTxHash: string | undefined - message: string | [string, InterpolationOptions] | undefined - }> - } catch (e) { - console.error(e) - return { - buyTxHash: undefined, - status: TxStatus.Unknown, - message: undefined, - } as unknown as Promise<{ - status: TxStatus - buyTxHash: string | undefined - message: string | [string, InterpolationOptions] | undefined - }> - } - }, + checkTradeStatus: checkSolanaSwapStatus, } diff --git a/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeQuote.ts b/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeQuote.ts index 81879dd8e2a..4b189175c30 100644 --- a/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeQuote.ts +++ b/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeQuote.ts @@ -6,6 +6,7 @@ import { fromAssetId, solAssetId, toAssetId, + wrappedSolAssetId, } from '@shapeshiftoss/caip' import type { GetFeeDataInput } from '@shapeshiftoss/chain-adapters' import type { KnownChainIds } from '@shapeshiftoss/types' @@ -68,8 +69,8 @@ const _getTradeQuote = async ( const maybeQuoteResponse = await getJupiterQuote({ apiUrl: jupiterUrl, - sourceAsset: sellAsset.assetId, - destinationAsset: buyAsset.assetId, + sourceAsset: sellAsset.assetId === solAssetId ? wrappedSolAssetId : sellAsset.assetId, + destinationAsset: buyAsset.assetId === solAssetId ? wrappedSolAssetId : buyAsset.assetId, commissionBps: affiliateBps, amount: sellAmount, slippageBps: convertDecimalPercentageToBasisPoints( diff --git a/packages/swapper/src/swappers/JupiterSwapper/utils/helpers.ts b/packages/swapper/src/swappers/JupiterSwapper/utils/helpers.ts index d36e8b64944..a47346de9c8 100644 --- a/packages/swapper/src/swappers/JupiterSwapper/utils/helpers.ts +++ b/packages/swapper/src/swappers/JupiterSwapper/utils/helpers.ts @@ -13,6 +13,8 @@ export const isSupportedChainId = (chainId: ChainId): chainId is JupiterSupporte return jupiterSupportedChainIds.includes(chainId as JupiterSupportedChainId) } +const SHAPESHIFT_SOLANA_FEE_ACCOUNT = 'C7RTJbss7R1r7j8NUNYbasUXfbPJR99PMhqznvCiU43N' + type GetJupiterQuoteArgs = { apiUrl: string sourceAsset: string @@ -25,8 +27,6 @@ type GetJupiterQuoteArgs = { type GetJupiterSwapArgs = { apiUrl: string fromAddress: string - // @TODO: make this mandatory when we have the DAO fee account - feeAccount?: string rawQuote: unknown } @@ -50,14 +50,13 @@ export const getJupiterQuote = ({ export const getJupiterSwapInstructions = ({ apiUrl, fromAddress, - feeAccount, rawQuote, }: GetJupiterSwapArgs): Promise< Result, SwapErrorRight> > => jupiterService.post(`${apiUrl}/swap-instructions`, { userPublicKey: fromAddress, - feeAccount, + feeAccount: SHAPESHIFT_SOLANA_FEE_ACCOUNT, quoteResponse: rawQuote, dynamicComputeUnitLimit: true, prioritizationFeeLamports: 'auto', diff --git a/packages/swapper/src/types.ts b/packages/swapper/src/types.ts index fbd381c4e8f..9f7b2e7256e 100644 --- a/packages/swapper/src/types.ts +++ b/packages/swapper/src/types.ts @@ -410,7 +410,8 @@ export type CheckTradeStatusInput = { config: SwapperConfig } & EvmSwapperDeps & UtxoSwapperDeps & - CosmosSdkSwapperDeps + CosmosSdkSwapperDeps & + SolanaSwapperDeps // a result containing all routes that were successfully generated, or an error in the case where // no routes could be generated diff --git a/packages/swapper/src/utils.ts b/packages/swapper/src/utils.ts index 5e39875e6a5..a230fc30aa3 100644 --- a/packages/swapper/src/utils.ts +++ b/packages/swapper/src/utils.ts @@ -1,5 +1,12 @@ -import { type AccountId, type AssetId, type ChainId, fromAssetId } from '@shapeshiftoss/caip' +import { + type AccountId, + type AssetId, + type ChainId, + fromAccountId, + fromAssetId, +} from '@shapeshiftoss/caip' import type { EvmChainAdapter } from '@shapeshiftoss/chain-adapters' +import type { ChainAdapter as SolanaChainAdapter } from '@shapeshiftoss/chain-adapters/dist/solana/SolanaChainAdapter' import type { SolanaSignTx } from '@shapeshiftoss/hdwallet-core' import type { Asset } from '@shapeshiftoss/types' import { evm, TxStatus } from '@shapeshiftoss/unchained-client' @@ -318,3 +325,37 @@ export const isToken = (assetId: AssetId) => { } export const isExecutableTradeStep = (step: TradeQuoteStep): step is ExecutableTradeStep => step.accountNumber !== undefined + +export const checkSolanaSwapStatus = async ({ + txHash, + chainId, + accountId, + assertGetSolanaChainAdapter, +}: { + txHash: string + accountId: AccountId | undefined + chainId: ChainId + assertGetSolanaChainAdapter: (chainId: ChainId) => SolanaChainAdapter +}): Promise<{ + status: TxStatus + buyTxHash: string | undefined + message: string | [string, InterpolationOptions] | undefined +}> => { + try { + if (!accountId) throw new Error('Missing accountId') + + const account = fromAccountId(accountId).account + const adapter = assertGetSolanaChainAdapter(chainId) + const tx = await adapter.httpProvider.getTransaction({ txid: txHash }) + const status = await adapter.getTxStatus(tx, account) + + return { + status, + buyTxHash: txHash, + message: undefined, + } + } catch (e) { + console.error(e) + return createDefaultStatusResponse(txHash) + } +} diff --git a/src/lib/tradeExecution.ts b/src/lib/tradeExecution.ts index 71b591e87da..ff580245941 100644 --- a/src/lib/tradeExecution.ts +++ b/src/lib/tradeExecution.ts @@ -104,6 +104,7 @@ export class TradeExecution { assertGetEvmChainAdapter, assertGetUtxoChainAdapter, assertGetCosmosSdkChainAdapter, + assertGetSolanaChainAdapter, fetchIsSmartContractAddressQuery, }) From c8b79965c9d6b377a9450f2b58586d35410d0754 Mon Sep 17 00:00:00 2001 From: NeOMakinG <14963751+NeOMakinG@users.noreply.github.com> Date: Fri, 15 Nov 2024 18:10:14 +0100 Subject: [PATCH 104/127] fix: comment fee address because cant use multisig --- .../swapper/src/swappers/JupiterSwapper/utils/helpers.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/swapper/src/swappers/JupiterSwapper/utils/helpers.ts b/packages/swapper/src/swappers/JupiterSwapper/utils/helpers.ts index a47346de9c8..e95f3737dfe 100644 --- a/packages/swapper/src/swappers/JupiterSwapper/utils/helpers.ts +++ b/packages/swapper/src/swappers/JupiterSwapper/utils/helpers.ts @@ -13,7 +13,7 @@ export const isSupportedChainId = (chainId: ChainId): chainId is JupiterSupporte return jupiterSupportedChainIds.includes(chainId as JupiterSupportedChainId) } -const SHAPESHIFT_SOLANA_FEE_ACCOUNT = 'C7RTJbss7R1r7j8NUNYbasUXfbPJR99PMhqznvCiU43N' +// const SHAPESHIFT_SOLANA_FEE_ACCOUNT = 'C7RTJbss7R1r7j8NUNYbasUXfbPJR99PMhqznvCiU43N' type GetJupiterQuoteArgs = { apiUrl: string @@ -56,7 +56,8 @@ export const getJupiterSwapInstructions = ({ > => jupiterService.post(`${apiUrl}/swap-instructions`, { userPublicKey: fromAddress, - feeAccount: SHAPESHIFT_SOLANA_FEE_ACCOUNT, + // feeAccount: SHAPESHIFT_SOLANA_FEE_ACCOUNT, + // feeAccount: '', quoteResponse: rawQuote, dynamicComputeUnitLimit: true, prioritizationFeeLamports: 'auto', From 9c1baa9b0556252b4b2c0f6163a0566529390793 Mon Sep 17 00:00:00 2001 From: NeOMakinG <14963751+NeOMakinG@users.noreply.github.com> Date: Mon, 18 Nov 2024 16:43:51 +0100 Subject: [PATCH 105/127] fix: add address lookup table --- package.json | 2 +- .../src/solana/SolanaChainAdapter.ts | 29 +++++++++++++++++++ packages/chain-adapters/src/solana/types.ts | 1 + .../src/swappers/JupiterSwapper/endpoints.ts | 1 + .../swapperApi/getTradeQuote.ts | 1 + .../swappers/JupiterSwapper/utils/helpers.ts | 3 ++ yarn.lock | 8 ++--- 7 files changed, 40 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index b9215efdac6..facbc73c227 100644 --- a/package.json +++ b/package.json @@ -103,7 +103,7 @@ "@shapeshiftoss/hdwallet-metamask-multichain": "1.55.12", "@shapeshiftoss/hdwallet-native": "1.55.12", "@shapeshiftoss/hdwallet-native-vault": "1.55.12", - "@shapeshiftoss/hdwallet-phantom": "1.55.12", + "@shapeshiftoss/hdwallet-phantom": "../hdwallet/packages/hdwallet-phantom", "@shapeshiftoss/hdwallet-walletconnectv2": "1.55.12", "@shapeshiftoss/swapper": "workspace:^", "@shapeshiftoss/types": "workspace:^", diff --git a/packages/chain-adapters/src/solana/SolanaChainAdapter.ts b/packages/chain-adapters/src/solana/SolanaChainAdapter.ts index a28c666b62f..70296c723ba 100644 --- a/packages/chain-adapters/src/solana/SolanaChainAdapter.ts +++ b/packages/chain-adapters/src/solana/SolanaChainAdapter.ts @@ -22,6 +22,7 @@ import { } from '@solana/spl-token' import type { TransactionInstruction } from '@solana/web3.js' import { + AddressLookupTableAccount, ComputeBudgetProgram, Connection, PublicKey, @@ -236,6 +237,10 @@ export class ChainAdapter implements IChainAdapter ) } + const addressLookupTableAccounts = await this.getAddressLookupTableAccounts( + chainSpecific.addressLookupTableAccounts ?? [], + ) + const txToSign: SignTx = { addressNList: toAddressNList(this.getBIP44Params({ accountNumber })), blockHash: blockhash, @@ -244,6 +249,7 @@ export class ChainAdapter implements IChainAdapter instructions, to: tokenId ? '' : to, value: tokenId ? '' : value, + addressLookupTableAccounts, } return { txToSign } @@ -540,4 +546,27 @@ export class ChainAdapter implements IChainAdapter get httpProvider(): unchained.solana.Api { return this.providers.http } + + public async getAddressLookupTableAccounts( + addresses: string[], + ): Promise { + const addressLookupTableAccountInfos = await this.connection.getMultipleAccountsInfo( + addresses.map(key => new PublicKey(key)), + ) + + return addressLookupTableAccountInfos.reduce((acc, accountInfo, index) => { + const addressLookupTableAddress = addresses[index] + if (accountInfo) { + const addressLookupTableAccount = new AddressLookupTableAccount({ + key: new PublicKey(addressLookupTableAddress), + state: AddressLookupTableAccount.deserialize( + new Uint8Array(Buffer.from(accountInfo.data)), + ), + }) + acc.push(addressLookupTableAccount) + } + + return acc + }, new Array()) + } } diff --git a/packages/chain-adapters/src/solana/types.ts b/packages/chain-adapters/src/solana/types.ts index a898f36d669..e20fae7dbcd 100644 --- a/packages/chain-adapters/src/solana/types.ts +++ b/packages/chain-adapters/src/solana/types.ts @@ -25,6 +25,7 @@ export type BuildTxInput = { computeUnitPrice?: string tokenId?: string instructions?: SolanaTxInstruction[] + addressLookupTableAccounts?: string[] } export type GetFeeDataInput = { diff --git a/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts b/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts index 88a1f6d85f7..f7417542ae2 100644 --- a/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts +++ b/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts @@ -72,6 +72,7 @@ export const jupiterApi: SwapperApi = { value: '0', accountNumber: step.accountNumber, chainSpecific: { + addressLookupTableAccounts: swapResponse.addressLookupTableAddresses, instructions: [...computeBudgetInstructions, ...setupInstructions, swapInstruction], }, } diff --git a/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeQuote.ts b/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeQuote.ts index 4b189175c30..21b151ca549 100644 --- a/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeQuote.ts +++ b/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeQuote.ts @@ -71,6 +71,7 @@ const _getTradeQuote = async ( apiUrl: jupiterUrl, sourceAsset: sellAsset.assetId === solAssetId ? wrappedSolAssetId : sellAsset.assetId, destinationAsset: buyAsset.assetId === solAssetId ? wrappedSolAssetId : buyAsset.assetId, + toAddress: receiveAddress, commissionBps: affiliateBps, amount: sellAmount, slippageBps: convertDecimalPercentageToBasisPoints( diff --git a/packages/swapper/src/swappers/JupiterSwapper/utils/helpers.ts b/packages/swapper/src/swappers/JupiterSwapper/utils/helpers.ts index e95f3737dfe..8de4d0d125a 100644 --- a/packages/swapper/src/swappers/JupiterSwapper/utils/helpers.ts +++ b/packages/swapper/src/swappers/JupiterSwapper/utils/helpers.ts @@ -22,6 +22,7 @@ type GetJupiterQuoteArgs = { commissionBps: string amount: string slippageBps?: string + toAddress: string } type GetJupiterSwapArgs = { @@ -34,6 +35,7 @@ export const getJupiterQuote = ({ apiUrl, sourceAsset, destinationAsset, + toAddress, commissionBps, amount, slippageBps, @@ -41,6 +43,7 @@ export const getJupiterQuote = ({ jupiterService.get( `${apiUrl}/quote` + `?inputMint=${fromAssetId(sourceAsset).assetReference}` + + `&destinationTokenAccount=${toAddress}` + `&outputMint=${fromAssetId(destinationAsset).assetReference}` + `&amount=${amount}` + `&slippageBps=${slippageBps}` + diff --git a/yarn.lock b/yarn.lock index f2b4532b81f..996cd3c8a5c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11451,9 +11451,9 @@ __metadata: languageName: node linkType: hard -"@shapeshiftoss/hdwallet-phantom@npm:1.55.12": +"@shapeshiftoss/hdwallet-phantom@file:../hdwallet/packages/hdwallet-phantom::locator=%40shapeshiftoss%2Fweb%40workspace%3A.": version: 1.55.12 - resolution: "@shapeshiftoss/hdwallet-phantom@npm:1.55.12" + resolution: "@shapeshiftoss/hdwallet-phantom@file:../hdwallet/packages/hdwallet-phantom#../hdwallet/packages/hdwallet-phantom::hash=31dd14&locator=%40shapeshiftoss%2Fweb%40workspace%3A." dependencies: "@shapeshiftoss/bitcoinjs-lib": 5.2.0-shapeshift.2 "@shapeshiftoss/hdwallet-core": 1.55.12 @@ -11462,7 +11462,7 @@ __metadata: bitcoinjs-message: ^2.0.0 ethers: 5.7.2 lodash: ^4.17.21 - checksum: eeaffafd3ccfb06b08349b5f45a28d0ce2b2c3677b625ff2dea29dd148b637074875c523acf7595e353868f18f9425af304ea0643de240682bc8802efdb23911 + checksum: 1e79337defbaee14298d6f51f4d79072881ac59199d07b11943bde1c53fdb579a7fd41bf39c3423e11679386f3228864b7343011ae99feb22de05df9d8367c44 languageName: node linkType: hard @@ -11682,7 +11682,7 @@ __metadata: "@shapeshiftoss/hdwallet-metamask-multichain": 1.55.12 "@shapeshiftoss/hdwallet-native": 1.55.12 "@shapeshiftoss/hdwallet-native-vault": 1.55.12 - "@shapeshiftoss/hdwallet-phantom": 1.55.12 + "@shapeshiftoss/hdwallet-phantom": ../hdwallet/packages/hdwallet-phantom "@shapeshiftoss/hdwallet-walletconnectv2": 1.55.12 "@shapeshiftoss/swapper": "workspace:^" "@shapeshiftoss/types": "workspace:^" From 08d1bab847f99079cc181e13f59c48c4ab45ef22 Mon Sep 17 00:00:00 2001 From: NeOMakinG <14963751+NeOMakinG@users.noreply.github.com> Date: Mon, 18 Nov 2024 16:48:14 +0100 Subject: [PATCH 106/127] fix: continue --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index facbc73c227..b9215efdac6 100644 --- a/package.json +++ b/package.json @@ -103,7 +103,7 @@ "@shapeshiftoss/hdwallet-metamask-multichain": "1.55.12", "@shapeshiftoss/hdwallet-native": "1.55.12", "@shapeshiftoss/hdwallet-native-vault": "1.55.12", - "@shapeshiftoss/hdwallet-phantom": "../hdwallet/packages/hdwallet-phantom", + "@shapeshiftoss/hdwallet-phantom": "1.55.12", "@shapeshiftoss/hdwallet-walletconnectv2": "1.55.12", "@shapeshiftoss/swapper": "workspace:^", "@shapeshiftoss/types": "workspace:^", diff --git a/yarn.lock b/yarn.lock index 996cd3c8a5c..f2b4532b81f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11451,9 +11451,9 @@ __metadata: languageName: node linkType: hard -"@shapeshiftoss/hdwallet-phantom@file:../hdwallet/packages/hdwallet-phantom::locator=%40shapeshiftoss%2Fweb%40workspace%3A.": +"@shapeshiftoss/hdwallet-phantom@npm:1.55.12": version: 1.55.12 - resolution: "@shapeshiftoss/hdwallet-phantom@file:../hdwallet/packages/hdwallet-phantom#../hdwallet/packages/hdwallet-phantom::hash=31dd14&locator=%40shapeshiftoss%2Fweb%40workspace%3A." + resolution: "@shapeshiftoss/hdwallet-phantom@npm:1.55.12" dependencies: "@shapeshiftoss/bitcoinjs-lib": 5.2.0-shapeshift.2 "@shapeshiftoss/hdwallet-core": 1.55.12 @@ -11462,7 +11462,7 @@ __metadata: bitcoinjs-message: ^2.0.0 ethers: 5.7.2 lodash: ^4.17.21 - checksum: 1e79337defbaee14298d6f51f4d79072881ac59199d07b11943bde1c53fdb579a7fd41bf39c3423e11679386f3228864b7343011ae99feb22de05df9d8367c44 + checksum: eeaffafd3ccfb06b08349b5f45a28d0ce2b2c3677b625ff2dea29dd148b637074875c523acf7595e353868f18f9425af304ea0643de240682bc8802efdb23911 languageName: node linkType: hard @@ -11682,7 +11682,7 @@ __metadata: "@shapeshiftoss/hdwallet-metamask-multichain": 1.55.12 "@shapeshiftoss/hdwallet-native": 1.55.12 "@shapeshiftoss/hdwallet-native-vault": 1.55.12 - "@shapeshiftoss/hdwallet-phantom": ../hdwallet/packages/hdwallet-phantom + "@shapeshiftoss/hdwallet-phantom": 1.55.12 "@shapeshiftoss/hdwallet-walletconnectv2": 1.55.12 "@shapeshiftoss/swapper": "workspace:^" "@shapeshiftoss/types": "workspace:^" From 3c8e8e2096aab85ee17d9db0b22774d3a27d82a9 Mon Sep 17 00:00:00 2001 From: NeOMakinG <14963751+NeOMakinG@users.noreply.github.com> Date: Mon, 18 Nov 2024 22:04:59 +0100 Subject: [PATCH 107/127] fix: pending --- .../src/solana/SolanaChainAdapter.ts | 2 +- .../src/swappers/JupiterSwapper/endpoints.ts | 26 +++++++++++++++++-- .../swapperApi/getTradeQuote.ts | 1 - .../swappers/JupiterSwapper/utils/helpers.ts | 6 ++--- src/state/helpers.ts | 2 +- 5 files changed, 29 insertions(+), 8 deletions(-) diff --git a/packages/chain-adapters/src/solana/SolanaChainAdapter.ts b/packages/chain-adapters/src/solana/SolanaChainAdapter.ts index 70296c723ba..880541c2145 100644 --- a/packages/chain-adapters/src/solana/SolanaChainAdapter.ts +++ b/packages/chain-adapters/src/solana/SolanaChainAdapter.ts @@ -458,7 +458,7 @@ export class ChainAdapter implements IChainAdapter return Buffer.from(transaction.serialize()).toString('base64') } - private async buildTokenTransferInstructions({ + public async buildTokenTransferInstructions({ from, to, tokenId, diff --git a/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts b/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts index f7417542ae2..b03093e4986 100644 --- a/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts +++ b/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts @@ -1,5 +1,6 @@ +import { fromAssetId, solAssetId } from '@shapeshiftoss/caip' import type { BuildSendApiTxInput } from '@shapeshiftoss/chain-adapters' -import type { SolanaSignTx } from '@shapeshiftoss/hdwallet-core' +import type { SolanaSignTx, SolanaTxInstruction } from '@shapeshiftoss/hdwallet-core' import type { KnownChainIds } from '@shapeshiftoss/types' import type { AxiosError } from 'axios' @@ -31,6 +32,7 @@ export const jupiterApi: SwapperApi = { const maybeSwapResponse = await getJupiterSwapInstructions({ apiUrl: jupiterUrl, fromAddress: from, + toAddress: tradeQuote.receiveAddress, rawQuote: tradeQuote.rawQuote, }) @@ -66,14 +68,34 @@ export const jupiterApi: SwapperApi = { const adapter = assertGetSolanaChainAdapter(step.sellAsset.chainId) + const contractAddress = + step.sellAsset.assetId === solAssetId + ? undefined + : fromAssetId(step.sellAsset.assetId).assetReference + + const createTokenAccountInstructions = !contractAddress + ? [] + : await adapter.buildTokenTransferInstructions({ + from, + to: tradeQuote.receiveAddress, + tokenId: contractAddress, + value: '0', + }) + const buildSwapTxInput: BuildSendApiTxInput = { to: '', from, value: '0', accountNumber: step.accountNumber, chainSpecific: { + tokenId: contractAddress, addressLookupTableAccounts: swapResponse.addressLookupTableAddresses, - instructions: [...computeBudgetInstructions, ...setupInstructions, swapInstruction], + instructions: [ + ...computeBudgetInstructions, + ...setupInstructions, + swapInstruction, + createTokenAccountInstructions[0] as unknown as SolanaTxInstruction, + ], }, } diff --git a/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeQuote.ts b/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeQuote.ts index 21b151ca549..4b189175c30 100644 --- a/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeQuote.ts +++ b/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeQuote.ts @@ -71,7 +71,6 @@ const _getTradeQuote = async ( apiUrl: jupiterUrl, sourceAsset: sellAsset.assetId === solAssetId ? wrappedSolAssetId : sellAsset.assetId, destinationAsset: buyAsset.assetId === solAssetId ? wrappedSolAssetId : buyAsset.assetId, - toAddress: receiveAddress, commissionBps: affiliateBps, amount: sellAmount, slippageBps: convertDecimalPercentageToBasisPoints( diff --git a/packages/swapper/src/swappers/JupiterSwapper/utils/helpers.ts b/packages/swapper/src/swappers/JupiterSwapper/utils/helpers.ts index 8de4d0d125a..aaed92bb7fe 100644 --- a/packages/swapper/src/swappers/JupiterSwapper/utils/helpers.ts +++ b/packages/swapper/src/swappers/JupiterSwapper/utils/helpers.ts @@ -22,20 +22,19 @@ type GetJupiterQuoteArgs = { commissionBps: string amount: string slippageBps?: string - toAddress: string } type GetJupiterSwapArgs = { apiUrl: string fromAddress: string rawQuote: unknown + toAddress: string } export const getJupiterQuote = ({ apiUrl, sourceAsset, destinationAsset, - toAddress, commissionBps, amount, slippageBps, @@ -43,7 +42,6 @@ export const getJupiterQuote = ({ jupiterService.get( `${apiUrl}/quote` + `?inputMint=${fromAssetId(sourceAsset).assetReference}` + - `&destinationTokenAccount=${toAddress}` + `&outputMint=${fromAssetId(destinationAsset).assetReference}` + `&amount=${amount}` + `&slippageBps=${slippageBps}` + @@ -53,12 +51,14 @@ export const getJupiterQuote = ({ export const getJupiterSwapInstructions = ({ apiUrl, fromAddress, + toAddress, rawQuote, }: GetJupiterSwapArgs): Promise< Result, SwapErrorRight> > => jupiterService.post(`${apiUrl}/swap-instructions`, { userPublicKey: fromAddress, + destinationTokenAccount: toAddress, // feeAccount: SHAPESHIFT_SOLANA_FEE_ACCOUNT, // feeAccount: '', quoteResponse: rawQuote, diff --git a/src/state/helpers.ts b/src/state/helpers.ts index b3b0d8d7226..72cac831b26 100644 --- a/src/state/helpers.ts +++ b/src/state/helpers.ts @@ -8,12 +8,12 @@ export const isCrossAccountTradeSupported = (swapperName: SwapperName) => { case SwapperName.Thorchain: case SwapperName.LIFI: case SwapperName.Chainflip: + case SwapperName.Jupiter: return true case SwapperName.Zrx: case SwapperName.CowSwap: case SwapperName.ArbitrumBridge: case SwapperName.Portals: - case SwapperName.Jupiter: case SwapperName.Test: // Technically supported for Arbitrum Bridge, but we disable it for the sake of simplicity for now return false From 6950fce9e830a8cc6d33b5784bdaa4174d689096 Mon Sep 17 00:00:00 2001 From: NeOMakinG <14963751+NeOMakinG@users.noreply.github.com> Date: Tue, 19 Nov 2024 01:37:25 +0100 Subject: [PATCH 108/127] fix: continue --- .../src/solana/SolanaChainAdapter.ts | 97 ++++++++++++-- packages/chain-adapters/src/solana/types.ts | 3 + .../src/swappers/JupiterSwapper/endpoints.ts | 122 +++++++++++++----- 3 files changed, 175 insertions(+), 47 deletions(-) diff --git a/packages/chain-adapters/src/solana/SolanaChainAdapter.ts b/packages/chain-adapters/src/solana/SolanaChainAdapter.ts index 880541c2145..c247694067c 100644 --- a/packages/chain-adapters/src/solana/SolanaChainAdapter.ts +++ b/packages/chain-adapters/src/solana/SolanaChainAdapter.ts @@ -345,21 +345,60 @@ export class ChainAdapter implements IChainAdapter .times(computeUnits) .plus(baseFee) .toFixed(0, BigNumber.ROUND_HALF_UP), - chainSpecific: { computeUnits, priorityFee: fast }, + chainSpecific: { + computeUnits, + priorityFee: fast, + computeUnitsInstruction: this.convertInstruction( + ComputeBudgetProgram.setComputeUnitLimit({ + units: Number(computeUnits), + }), + ), + computeUnitsPriceInstruction: this.convertInstruction( + ComputeBudgetProgram.setComputeUnitPrice({ + microLamports: Number(fast), + }), + ), + }, }, average: { txFee: bn(microLamportsToLamports(average)) .times(computeUnits) .plus(baseFee) .toFixed(0, BigNumber.ROUND_HALF_UP), - chainSpecific: { computeUnits, priorityFee: average }, + chainSpecific: { + computeUnits, + priorityFee: average, + computeUnitsInstruction: this.convertInstruction( + ComputeBudgetProgram.setComputeUnitLimit({ + units: Number(computeUnits), + }), + ), + computeUnitsPriceInstruction: this.convertInstruction( + ComputeBudgetProgram.setComputeUnitPrice({ + microLamports: Number(average), + }), + ), + }, }, slow: { txFee: bn(microLamportsToLamports(slow)) .times(computeUnits) .plus(baseFee) .toFixed(0, BigNumber.ROUND_HALF_UP), - chainSpecific: { computeUnits, priorityFee: slow }, + chainSpecific: { + computeUnits, + priorityFee: slow, + computeUnitsInstruction: this.convertInstruction( + ComputeBudgetProgram.setComputeUnitLimit({ + units: Number(computeUnits), + }), + ), + computeUnitsPriceInstruction: this.convertInstruction( + ComputeBudgetProgram.setComputeUnitPrice({ + microLamports: Number(slow), + }), + ), + }, }, } } @@ -413,6 +452,10 @@ export class ChainAdapter implements IChainAdapter const { to, chainSpecific } = input const { from, tokenId, instructions = [] } = chainSpecific + const addressLookupTableAccounts = await this.getAddressLookupTableAccounts( + chainSpecific.addressLookupTableAccounts ?? [], + ) + if (!to) throw new Error(`${this.getName()}ChainAdapter: to is required`) if (!input.value) throw new Error(`${this.getName()}ChainAdapter: value is required`) @@ -451,26 +494,25 @@ export class ChainAdapter implements IChainAdapter instructions, // static block hash as fee estimation replaces the block hash with latest to save us a client side call recentBlockhash: '4sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZAMdL4VZHirAn', - }).compileToV0Message() + }).compileToV0Message(addressLookupTableAccounts) const transaction = new VersionedTransaction(message) return Buffer.from(transaction.serialize()).toString('base64') } - public async buildTokenTransferInstructions({ + public async createAssociatedTokenAccountInstruction({ from, to, tokenId, - value, }: { from: string to: string tokenId: string - value: string - }): Promise { - const instructions: TransactionInstruction[] = [] - + }): Promise<{ + instruction?: TransactionInstruction + destinationTokenAccount: PublicKey + }> { const destinationTokenAccount = getAssociatedTokenAddressSync( new PublicKey(tokenId), new PublicKey(to), @@ -485,18 +527,45 @@ export class ChainAdapter implements IChainAdapter err instanceof TokenAccountNotFoundError || err instanceof TokenInvalidAccountOwnerError ) { - instructions.push( - createAssociatedTokenAccountInstruction( + return { + instruction: createAssociatedTokenAccountInstruction( // sender pays for creation of the token account new PublicKey(from), destinationTokenAccount, new PublicKey(to), new PublicKey(tokenId), ), - ) + destinationTokenAccount, + } } } + return { + instruction: undefined, + destinationTokenAccount, + } + } + + private async buildTokenTransferInstructions({ + from, + to, + tokenId, + value, + }: { + from: string + to: string + tokenId: string + value: string + }): Promise { + const instructions: TransactionInstruction[] = [] + + const { instruction, destinationTokenAccount } = + await this.createAssociatedTokenAccountInstruction({ from, to, tokenId }) + + if (instruction) { + instructions.push(instruction) + } + instructions.push( createTransferInstruction( getAssociatedTokenAddressSync(new PublicKey(tokenId), new PublicKey(from), true), @@ -509,7 +578,7 @@ export class ChainAdapter implements IChainAdapter return instructions } - private convertInstruction(instruction: TransactionInstruction): SolanaTxInstruction { + public convertInstruction(instruction: TransactionInstruction): SolanaTxInstruction { return { keys: instruction.keys.map(key => ({ pubkey: key.pubkey.toString(), diff --git a/packages/chain-adapters/src/solana/types.ts b/packages/chain-adapters/src/solana/types.ts index e20fae7dbcd..22ee4bf222f 100644 --- a/packages/chain-adapters/src/solana/types.ts +++ b/packages/chain-adapters/src/solana/types.ts @@ -32,11 +32,14 @@ export type GetFeeDataInput = { from: string tokenId?: string instructions?: TransactionInstruction[] + addressLookupTableAccounts?: string[] } export type FeeData = { computeUnits: string priorityFee: string + computeUnitsInstruction: SolanaTxInstruction + computeUnitsPriceInstruction: SolanaTxInstruction } export type PriorityFeeData = { diff --git a/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts b/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts index b03093e4986..1427ff6c65a 100644 --- a/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts +++ b/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts @@ -1,7 +1,8 @@ -import { fromAssetId, solAssetId } from '@shapeshiftoss/caip' -import type { BuildSendApiTxInput } from '@shapeshiftoss/chain-adapters' +import { CHAIN_NAMESPACE, fromAssetId, solAssetId } from '@shapeshiftoss/caip' +import type { BuildSendApiTxInput, GetFeeDataInput } from '@shapeshiftoss/chain-adapters' import type { SolanaSignTx, SolanaTxInstruction } from '@shapeshiftoss/hdwallet-core' import type { KnownChainIds } from '@shapeshiftoss/types' +import { PublicKey, type TransactionInstruction } from '@solana/web3.js' import type { AxiosError } from 'axios' import type { GetUnsignedSolanaTransactionArgs } from '../../types' @@ -29,10 +30,33 @@ export const jupiterApi: SwapperApi = { if (!tradeQuote.rawQuote) throw Error('Missing raw quote') + const contractAddress = + step.sellAsset.assetId === solAssetId + ? undefined + : fromAssetId(step.sellAsset.assetId).assetReference + + const adapter = assertGetSolanaChainAdapter(step.sellAsset.chainId) + + const { instruction: createTokenAccountInstruction, destinationTokenAccount } = + await (async () => { + if (contractAddress) { + return await adapter.createAssociatedTokenAccountInstruction({ + from, + to: tradeQuote.receiveAddress, + tokenId: contractAddress, + }) + } + + return { + instruction: undefined, + destinationTokenAccount: undefined, + } + })() + const maybeSwapResponse = await getJupiterSwapInstructions({ apiUrl: jupiterUrl, fromAddress: from, - toAddress: tradeQuote.receiveAddress, + toAddress: destinationTokenAccount?.toString() ?? tradeQuote.receiveAddress, rawQuote: tradeQuote.rawQuote, }) @@ -44,43 +68,81 @@ export const jupiterApi: SwapperApi = { const { data: swapResponse } = maybeSwapResponse.unwrap() - const computeBudgetInstructions = swapResponse.computeBudgetInstructions.map(instruction => { - return { - ...instruction, - keys: instruction.accounts, - data: Buffer.from(instruction.data, 'base64'), - } - }) - const setupInstructions = swapResponse.setupInstructions.map(instruction => { return { ...instruction, - keys: instruction.accounts, + keys: swapResponse.swapInstruction.accounts.map(account => { + return { + ...account, + pubkey: new PublicKey(account.pubkey), + } + }), data: Buffer.from(instruction.data, 'base64'), + programId: new PublicKey(swapResponse.swapInstruction.programId), } }) const swapInstruction = { ...swapResponse.swapInstruction, - keys: swapResponse.swapInstruction.accounts, + keys: swapResponse.swapInstruction.accounts.map(account => { + return { + ...account, + pubkey: new PublicKey(account.pubkey), + } + }), data: Buffer.from(swapResponse.swapInstruction.data, 'base64'), + programId: new PublicKey(swapResponse.swapInstruction.programId), } - const adapter = assertGetSolanaChainAdapter(step.sellAsset.chainId) + const instructions = [ + ...setupInstructions, + swapInstruction, + ] as unknown as TransactionInstruction[] - const contractAddress = - step.sellAsset.assetId === solAssetId - ? undefined - : fromAssetId(step.sellAsset.assetId).assetReference + if (createTokenAccountInstruction) { + instructions.unshift(createTokenAccountInstruction) + } - const createTokenAccountInstructions = !contractAddress - ? [] - : await adapter.buildTokenTransferInstructions({ - from, - to: tradeQuote.receiveAddress, - tokenId: contractAddress, - value: '0', - }) + const getFeeData = async () => { + const { chainNamespace } = fromAssetId(step.sellAsset.assetId) + + switch (chainNamespace) { + case CHAIN_NAMESPACE.Solana: { + const sellAdapter = assertGetSolanaChainAdapter(step.sellAsset.chainId) + const getFeeDataInput: GetFeeDataInput = { + // Simulates a self-send + to: from, + value: '0', + chainSpecific: { + from, + addressLookupTableAccounts: swapResponse.addressLookupTableAddresses, + instructions, + }, + } + const { fast } = await sellAdapter.getFeeData(getFeeDataInput) + return fast + } + + default: + throw new Error('Unsupported chainNamespace') + } + } + + const { + chainSpecific: { computeUnitsInstruction, computeUnitsPriceInstruction }, + } = await getFeeData() + + const solanaInstructions: SolanaTxInstruction[] = [ + ...setupInstructions.map(instruction => adapter.convertInstruction(instruction)), + adapter.convertInstruction(swapInstruction), + ] + + solanaInstructions.unshift(computeUnitsInstruction) + solanaInstructions.unshift(computeUnitsPriceInstruction) + + if (createTokenAccountInstruction) { + solanaInstructions.unshift(adapter.convertInstruction(createTokenAccountInstruction)) + } const buildSwapTxInput: BuildSendApiTxInput = { to: '', @@ -88,14 +150,8 @@ export const jupiterApi: SwapperApi = { value: '0', accountNumber: step.accountNumber, chainSpecific: { - tokenId: contractAddress, addressLookupTableAccounts: swapResponse.addressLookupTableAddresses, - instructions: [ - ...computeBudgetInstructions, - ...setupInstructions, - swapInstruction, - createTokenAccountInstructions[0] as unknown as SolanaTxInstruction, - ], + instructions: solanaInstructions, }, } From 1ba279b893e732bea7174bbf6ba65de3a2febb38 Mon Sep 17 00:00:00 2001 From: NeOMakinG <14963751+NeOMakinG@users.noreply.github.com> Date: Tue, 19 Nov 2024 18:19:10 +0100 Subject: [PATCH 109/127] fix: finish --- package.json | 2 +- .../getCowSwapTradeQuote.test.ts | 6 ++ .../src/swappers/JupiterSwapper/endpoints.ts | 98 ++++++++----------- .../swapperApi/getTradeQuote.ts | 10 ++ .../swappers/JupiterSwapper/utils/helpers.ts | 13 ++- .../utils/test-data/setupSwapQuote.ts | 1 + packages/swapper/src/types.ts | 5 +- .../useGetTradeQuotes/getTradeQuoteInput.ts | 4 + .../useGetTradeQuotes/useGetTradeQuotes.tsx | 2 + src/components/MultiHopTrade/types.ts | 1 + .../Stake/Bridge/hooks/useRfoxBridge.ts | 1 + yarn.lock | 8 +- 12 files changed, 84 insertions(+), 67 deletions(-) diff --git a/package.json b/package.json index b9215efdac6..facbc73c227 100644 --- a/package.json +++ b/package.json @@ -103,7 +103,7 @@ "@shapeshiftoss/hdwallet-metamask-multichain": "1.55.12", "@shapeshiftoss/hdwallet-native": "1.55.12", "@shapeshiftoss/hdwallet-native-vault": "1.55.12", - "@shapeshiftoss/hdwallet-phantom": "1.55.12", + "@shapeshiftoss/hdwallet-phantom": "../hdwallet/packages/hdwallet-phantom", "@shapeshiftoss/hdwallet-walletconnectv2": "1.55.12", "@shapeshiftoss/swapper": "workspace:^", "@shapeshiftoss/types": "workspace:^", diff --git a/packages/swapper/src/swappers/CowSwapper/getCowSwapTradeQuote/getCowSwapTradeQuote.test.ts b/packages/swapper/src/swappers/CowSwapper/getCowSwapTradeQuote/getCowSwapTradeQuote.test.ts index 316221c3ee5..be5712cd573 100644 --- a/packages/swapper/src/swappers/CowSwapper/getCowSwapTradeQuote/getCowSwapTradeQuote.test.ts +++ b/packages/swapper/src/swappers/CowSwapper/getCowSwapTradeQuote/getCowSwapTradeQuote.test.ts @@ -312,6 +312,7 @@ describe('getCowSwapTradeQuote', () => { sellAmountIncludingProtocolFeesCryptoBaseUnit: '11111', accountNumber: 0, receiveAddress: DEFAULT_ADDRESS, + isManualReceiveAddress: false, affiliateBps: '0', potentialAffiliateBps: '0', supportsEIP1559: false, @@ -339,6 +340,7 @@ describe('getCowSwapTradeQuote', () => { sellAmountIncludingProtocolFeesCryptoBaseUnit: '1000000000000000000', accountNumber: 0, receiveAddress: DEFAULT_ADDRESS, + isManualReceiveAddress: false, affiliateBps: '0', potentialAffiliateBps: '0', supportsEIP1559: false, @@ -384,6 +386,7 @@ describe('getCowSwapTradeQuote', () => { sellAmountIncludingProtocolFeesCryptoBaseUnit: '1000000000000000000000', accountNumber: 0, receiveAddress: DEFAULT_ADDRESS, + isManualReceiveAddress: false, affiliateBps: '0', potentialAffiliateBps: '0', supportsEIP1559: false, @@ -429,6 +432,7 @@ describe('getCowSwapTradeQuote', () => { sellAmountIncludingProtocolFeesCryptoBaseUnit: '20000000', accountNumber: 0, receiveAddress: DEFAULT_ADDRESS, + isManualReceiveAddress: false, affiliateBps: '0', potentialAffiliateBps: '0', supportsEIP1559: false, @@ -474,6 +478,7 @@ describe('getCowSwapTradeQuote', () => { sellAmountIncludingProtocolFeesCryptoBaseUnit: '500000', accountNumber: 0, receiveAddress: DEFAULT_ADDRESS, + isManualReceiveAddress: false, affiliateBps: '0', potentialAffiliateBps: '0', supportsEIP1559: false, @@ -519,6 +524,7 @@ describe('getCowSwapTradeQuote', () => { sellAmountIncludingProtocolFeesCryptoBaseUnit: '1000000000000', accountNumber: 0, receiveAddress: DEFAULT_ADDRESS, + isManualReceiveAddress: false, affiliateBps: '0', potentialAffiliateBps: '0', supportsEIP1559: false, diff --git a/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts b/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts index 1427ff6c65a..1b5e541584d 100644 --- a/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts +++ b/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts @@ -1,6 +1,6 @@ import { CHAIN_NAMESPACE, fromAssetId, solAssetId } from '@shapeshiftoss/caip' import type { BuildSendApiTxInput, GetFeeDataInput } from '@shapeshiftoss/chain-adapters' -import type { SolanaSignTx, SolanaTxInstruction } from '@shapeshiftoss/hdwallet-core' +import type { SolanaSignTx } from '@shapeshiftoss/hdwallet-core' import type { KnownChainIds } from '@shapeshiftoss/types' import { PublicKey, type TransactionInstruction } from '@solana/web3.js' import type { AxiosError } from 'axios' @@ -8,6 +8,7 @@ import type { AxiosError } from 'axios' import type { GetUnsignedSolanaTransactionArgs } from '../../types' import { type SwapperApi } from '../../types' import { checkSolanaSwapStatus, isExecutableTradeQuote, isExecutableTradeStep } from '../../utils' +import type { Instruction } from './models/Instruction' import { getTradeQuote, getTradeRate } from './swapperApi/getTradeQuote' import { getJupiterSwapInstructions } from './utils/helpers' @@ -31,33 +32,35 @@ export const jupiterApi: SwapperApi = { if (!tradeQuote.rawQuote) throw Error('Missing raw quote') const contractAddress = - step.sellAsset.assetId === solAssetId + step.buyAsset.assetId === solAssetId ? undefined - : fromAssetId(step.sellAsset.assetId).assetReference + : fromAssetId(step.buyAsset.assetId).assetReference const adapter = assertGetSolanaChainAdapter(step.sellAsset.chainId) + const isManualReceiveAddress = tradeQuote.receiveAddress !== from + + if (isManualReceiveAddress && step.buyAsset.assetId === solAssetId) { + throw Error('Manual receive address is not supported for SOL') + } + const { instruction: createTokenAccountInstruction, destinationTokenAccount } = - await (async () => { - if (contractAddress) { - return await adapter.createAssociatedTokenAccountInstruction({ + contractAddress && isManualReceiveAddress + ? await adapter.createAssociatedTokenAccountInstruction({ from, to: tradeQuote.receiveAddress, tokenId: contractAddress, }) - } - - return { - instruction: undefined, - destinationTokenAccount: undefined, - } - })() + : { instruction: undefined, destinationTokenAccount: undefined } const maybeSwapResponse = await getJupiterSwapInstructions({ apiUrl: jupiterUrl, fromAddress: from, - toAddress: destinationTokenAccount?.toString() ?? tradeQuote.receiveAddress, + toAddress: isManualReceiveAddress ? destinationTokenAccount?.toString() : undefined, rawQuote: tradeQuote.rawQuote, + // Shared account is not supported for simple AMMs + useSharedAccounts: + tradeQuote.rawQuote.routePlan.length > 1 && isManualReceiveAddress ? true : false, }) if (maybeSwapResponse.isErr()) { @@ -68,41 +71,29 @@ export const jupiterApi: SwapperApi = { const { data: swapResponse } = maybeSwapResponse.unwrap() - const setupInstructions = swapResponse.setupInstructions.map(instruction => { - return { - ...instruction, - keys: swapResponse.swapInstruction.accounts.map(account => { - return { - ...account, - pubkey: new PublicKey(account.pubkey), - } - }), - data: Buffer.from(instruction.data, 'base64'), - programId: new PublicKey(swapResponse.swapInstruction.programId), - } + const convertJupiterInstruction = (instruction: Instruction): TransactionInstruction => ({ + ...instruction, + keys: instruction.accounts.map(account => ({ + ...account, + pubkey: new PublicKey(account.pubkey), + })), + data: Buffer.from(instruction.data, 'base64'), + programId: new PublicKey(instruction.programId), }) - const swapInstruction = { - ...swapResponse.swapInstruction, - keys: swapResponse.swapInstruction.accounts.map(account => { - return { - ...account, - pubkey: new PublicKey(account.pubkey), - } - }), - data: Buffer.from(swapResponse.swapInstruction.data, 'base64'), - programId: new PublicKey(swapResponse.swapInstruction.programId), - } - - const instructions = [ - ...setupInstructions, - swapInstruction, - ] as unknown as TransactionInstruction[] + const instructions: TransactionInstruction[] = [ + ...swapResponse.setupInstructions.map(convertJupiterInstruction), + convertJupiterInstruction(swapResponse.swapInstruction), + ] if (createTokenAccountInstruction) { instructions.unshift(createTokenAccountInstruction) } + if (swapResponse.cleanupInstruction) { + instructions.push(convertJupiterInstruction(swapResponse.cleanupInstruction)) + } + const getFeeData = async () => { const { chainNamespace } = fromAssetId(step.sellAsset.assetId) @@ -119,8 +110,7 @@ export const jupiterApi: SwapperApi = { instructions, }, } - const { fast } = await sellAdapter.getFeeData(getFeeDataInput) - return fast + return await sellAdapter.getFeeData(getFeeDataInput) } default: @@ -128,21 +118,11 @@ export const jupiterApi: SwapperApi = { } } - const { - chainSpecific: { computeUnitsInstruction, computeUnitsPriceInstruction }, - } = await getFeeData() + const { fast } = await getFeeData() - const solanaInstructions: SolanaTxInstruction[] = [ - ...setupInstructions.map(instruction => adapter.convertInstruction(instruction)), - adapter.convertInstruction(swapInstruction), - ] - - solanaInstructions.unshift(computeUnitsInstruction) - solanaInstructions.unshift(computeUnitsPriceInstruction) - - if (createTokenAccountInstruction) { - solanaInstructions.unshift(adapter.convertInstruction(createTokenAccountInstruction)) - } + const solanaInstructions = instructions.map(instruction => + adapter.convertInstruction(instruction), + ) const buildSwapTxInput: BuildSendApiTxInput = { to: '', @@ -152,6 +132,8 @@ export const jupiterApi: SwapperApi = { chainSpecific: { addressLookupTableAccounts: swapResponse.addressLookupTableAddresses, instructions: solanaInstructions, + computeUnitLimit: fast.chainSpecific.computeUnits, + computeUnitPrice: fast.chainSpecific.priorityFee, }, } diff --git a/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeQuote.ts b/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeQuote.ts index 4b189175c30..dcbccb8d6f9 100644 --- a/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeQuote.ts +++ b/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeQuote.ts @@ -41,12 +41,22 @@ const _getTradeQuote = async ( receiveAddress, accountNumber, slippageTolerancePercentageDecimal, + isManualReceiveAddress, } = input const { assetsById } = deps const jupiterUrl = deps.config.REACT_APP_JUPITER_API_URL + if (isManualReceiveAddress && buyAsset.assetId === solAssetId) { + return Err( + makeSwapErrorRight({ + message: `unsupported manual receive address for SOL`, + code: TradeQuoteError.UnsupportedTradePair, + }), + ) + } + if (!isSupportedChainId(sellAsset.chainId)) { return Err( makeSwapErrorRight({ diff --git a/packages/swapper/src/swappers/JupiterSwapper/utils/helpers.ts b/packages/swapper/src/swappers/JupiterSwapper/utils/helpers.ts index aaed92bb7fe..35f2f1629f9 100644 --- a/packages/swapper/src/swappers/JupiterSwapper/utils/helpers.ts +++ b/packages/swapper/src/swappers/JupiterSwapper/utils/helpers.ts @@ -13,6 +13,8 @@ export const isSupportedChainId = (chainId: ChainId): chainId is JupiterSupporte return jupiterSupportedChainIds.includes(chainId as JupiterSupportedChainId) } +const JUPITER_TRANSACTION_MAX_ACCOUNTS = 54 + // const SHAPESHIFT_SOLANA_FEE_ACCOUNT = 'C7RTJbss7R1r7j8NUNYbasUXfbPJR99PMhqznvCiU43N' type GetJupiterQuoteArgs = { @@ -28,7 +30,9 @@ type GetJupiterSwapArgs = { apiUrl: string fromAddress: string rawQuote: unknown - toAddress: string + toAddress?: string + useSharedAccounts: boolean + wrapAndUnwrapSol?: boolean } export const getJupiterQuote = ({ @@ -45,6 +49,7 @@ export const getJupiterQuote = ({ `&outputMint=${fromAssetId(destinationAsset).assetReference}` + `&amount=${amount}` + `&slippageBps=${slippageBps}` + + `&maxAccounts=${JUPITER_TRANSACTION_MAX_ACCOUNTS}` + `&platformFeeBps=${commissionBps}`, ) @@ -53,15 +58,17 @@ export const getJupiterSwapInstructions = ({ fromAddress, toAddress, rawQuote, + useSharedAccounts, + wrapAndUnwrapSol = true, }: GetJupiterSwapArgs): Promise< Result, SwapErrorRight> > => jupiterService.post(`${apiUrl}/swap-instructions`, { userPublicKey: fromAddress, destinationTokenAccount: toAddress, - // feeAccount: SHAPESHIFT_SOLANA_FEE_ACCOUNT, - // feeAccount: '', + useSharedAccounts, quoteResponse: rawQuote, dynamicComputeUnitLimit: true, prioritizationFeeLamports: 'auto', + wrapAndUnwrapSol, }) diff --git a/packages/swapper/src/swappers/utils/test-data/setupSwapQuote.ts b/packages/swapper/src/swappers/utils/test-data/setupSwapQuote.ts index 72deb5d7a15..141a941b6fb 100644 --- a/packages/swapper/src/swappers/utils/test-data/setupSwapQuote.ts +++ b/packages/swapper/src/swappers/utils/test-data/setupSwapQuote.ts @@ -43,6 +43,7 @@ export const setupQuote = () => { buyAsset, accountNumber: 0, receiveAddress: '0xc770eefad204b5180df6a14ee197d99d808ee52d', + isManualReceiveAddress: false, affiliateBps: '0', potentialAffiliateBps: '0', supportsEIP1559: false, diff --git a/packages/swapper/src/types.ts b/packages/swapper/src/types.ts index 9f7b2e7256e..e3b15877c15 100644 --- a/packages/swapper/src/types.ts +++ b/packages/swapper/src/types.ts @@ -26,6 +26,7 @@ import type { InterpolationOptions } from 'node-polyglot' import type { TransactionRequest } from 'viem' import type { CowMessageToSign } from './swappers/CowSwapper/types' +import type { QuoteResponse } from './swappers/JupiterSwapper/models/QuoteResponse' import type { makeSwapperAxiosServiceMonadic } from './utils' // TODO: Rename all properties in this type to be camel case and not react specific @@ -146,6 +147,7 @@ type CommonTradeInputBase = { export type CommonTradeQuoteInput = CommonTradeInputBase & { sendAddress?: string receiveAddress: string + isManualReceiveAddress: boolean accountNumber: number quoteOrRate: 'quote' } @@ -153,6 +155,7 @@ export type CommonTradeQuoteInput = CommonTradeInputBase & { type CommonTradeRateInput = CommonTradeInputBase & { sendAddress?: undefined receiveAddress: undefined + isManualReceiveAddress: boolean accountNumber: undefined quoteOrRate: 'rate' } @@ -267,7 +270,7 @@ type TradeQuoteBase = { isStreaming?: boolean slippageTolerancePercentageDecimal: string | undefined // undefined if slippage limit is not provided or specified by the swapper isLongtail?: boolean - rawQuote?: unknown + rawQuote?: QuoteResponse } type TradeRateBase = Omit & { receiveAddress: undefined } diff --git a/src/components/MultiHopTrade/hooks/useGetTradeQuotes/getTradeQuoteInput.ts b/src/components/MultiHopTrade/hooks/useGetTradeQuotes/getTradeQuoteInput.ts index b4fd70e0791..cb15e7a3dad 100644 --- a/src/components/MultiHopTrade/hooks/useGetTradeQuotes/getTradeQuoteInput.ts +++ b/src/components/MultiHopTrade/hooks/useGetTradeQuotes/getTradeQuoteInput.ts @@ -28,6 +28,7 @@ export type GetTradeQuoteInputArgs = { pubKey?: string | undefined quoteOrRate: 'quote' | 'rate' receiveAddress: string | undefined + isManualReceiveAddress: boolean sellAccountNumber: number | undefined wallet: HDWallet | undefined } @@ -46,6 +47,7 @@ export const getTradeQuoteInput = async ({ potentialAffiliateBps, slippageTolerancePercentageDecimal, pubKey, + isManualReceiveAddress, }: GetTradeQuoteInputArgs): Promise => { const tradeQuoteInputCommonArgs: TradeQuoteInputCommonArgs = { sellAmountIncludingProtocolFeesCryptoBaseUnit: toBaseUnit( @@ -55,6 +57,7 @@ export const getTradeQuoteInput = async ({ sellAsset, buyAsset, receiveAddress, + isManualReceiveAddress, accountNumber: sellAccountNumber, affiliateBps: affiliateBps ?? '0', potentialAffiliateBps: potentialAffiliateBps ?? '0', @@ -137,6 +140,7 @@ export const getTradeQuoteInput = async ({ const xpub = pubKey ?? (await sellAssetChainAdapter.getPublicKey(wallet, sellAccountNumber, sellAccountType)).xpub + return { ...tradeQuoteInputCommonArgs, chainId: sellAsset.chainId as UtxoChainId, diff --git a/src/components/MultiHopTrade/hooks/useGetTradeQuotes/useGetTradeQuotes.tsx b/src/components/MultiHopTrade/hooks/useGetTradeQuotes/useGetTradeQuotes.tsx index 8c958e7e8c4..e91430bd77a 100644 --- a/src/components/MultiHopTrade/hooks/useGetTradeQuotes/useGetTradeQuotes.tsx +++ b/src/components/MultiHopTrade/hooks/useGetTradeQuotes/useGetTradeQuotes.tsx @@ -241,6 +241,7 @@ export const useGetTradeQuotes = () => { wallet: wallet ?? undefined, quoteOrRate, receiveAddress, + isManualReceiveAddress: Boolean(manualReceiveAddress), sellAmountBeforeFeesCryptoPrecision: sellAmountCryptoPrecision, allowMultiHop: true, affiliateBps, @@ -272,6 +273,7 @@ export const useGetTradeQuotes = () => { isVotingPowerLoading, isBuyAssetChainSupported, quoteOrRate, + manualReceiveAddress, ]) const getTradeQuoteArgs = useCallback( diff --git a/src/components/MultiHopTrade/types.ts b/src/components/MultiHopTrade/types.ts index 11aebb2aae9..970e6c22ff0 100644 --- a/src/components/MultiHopTrade/types.ts +++ b/src/components/MultiHopTrade/types.ts @@ -26,6 +26,7 @@ export type TradeQuoteInputCommonArgs = Pick< | 'sellAsset' | 'buyAsset' | 'receiveAddress' + | 'isManualReceiveAddress' | 'accountNumber' | 'affiliateBps' | 'potentialAffiliateBps' diff --git a/src/pages/RFOX/components/Stake/Bridge/hooks/useRfoxBridge.ts b/src/pages/RFOX/components/Stake/Bridge/hooks/useRfoxBridge.ts index 9d34d29d2cd..681ceb9ca7e 100644 --- a/src/pages/RFOX/components/Stake/Bridge/hooks/useRfoxBridge.ts +++ b/src/pages/RFOX/components/Stake/Bridge/hooks/useRfoxBridge.ts @@ -141,6 +141,7 @@ export const useRfoxBridge = ({ confirmedQuote }: UseRfoxBridgeProps): UseRfoxBr potentialAffiliateBps: '0', allowMultiHop: true, receiveAddress: fromAccountId(confirmedQuote.buyAssetAccountId).account, + isManualReceiveAddress: false, sendAddress: fromAccountId(confirmedQuote.sellAssetAccountId).account, accountNumber: sellAssetAccountNumber, hasWallet: Boolean(walletInfo?.deviceId), diff --git a/yarn.lock b/yarn.lock index f2b4532b81f..996cd3c8a5c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11451,9 +11451,9 @@ __metadata: languageName: node linkType: hard -"@shapeshiftoss/hdwallet-phantom@npm:1.55.12": +"@shapeshiftoss/hdwallet-phantom@file:../hdwallet/packages/hdwallet-phantom::locator=%40shapeshiftoss%2Fweb%40workspace%3A.": version: 1.55.12 - resolution: "@shapeshiftoss/hdwallet-phantom@npm:1.55.12" + resolution: "@shapeshiftoss/hdwallet-phantom@file:../hdwallet/packages/hdwallet-phantom#../hdwallet/packages/hdwallet-phantom::hash=31dd14&locator=%40shapeshiftoss%2Fweb%40workspace%3A." dependencies: "@shapeshiftoss/bitcoinjs-lib": 5.2.0-shapeshift.2 "@shapeshiftoss/hdwallet-core": 1.55.12 @@ -11462,7 +11462,7 @@ __metadata: bitcoinjs-message: ^2.0.0 ethers: 5.7.2 lodash: ^4.17.21 - checksum: eeaffafd3ccfb06b08349b5f45a28d0ce2b2c3677b625ff2dea29dd148b637074875c523acf7595e353868f18f9425af304ea0643de240682bc8802efdb23911 + checksum: 1e79337defbaee14298d6f51f4d79072881ac59199d07b11943bde1c53fdb579a7fd41bf39c3423e11679386f3228864b7343011ae99feb22de05df9d8367c44 languageName: node linkType: hard @@ -11682,7 +11682,7 @@ __metadata: "@shapeshiftoss/hdwallet-metamask-multichain": 1.55.12 "@shapeshiftoss/hdwallet-native": 1.55.12 "@shapeshiftoss/hdwallet-native-vault": 1.55.12 - "@shapeshiftoss/hdwallet-phantom": 1.55.12 + "@shapeshiftoss/hdwallet-phantom": ../hdwallet/packages/hdwallet-phantom "@shapeshiftoss/hdwallet-walletconnectv2": 1.55.12 "@shapeshiftoss/swapper": "workspace:^" "@shapeshiftoss/types": "workspace:^" From b91378721a9a1dc69bcd9edd3859863ebfbc7e5c Mon Sep 17 00:00:00 2001 From: NeOMakinG <14963751+NeOMakinG@users.noreply.github.com> Date: Tue, 19 Nov 2024 18:20:43 +0100 Subject: [PATCH 110/127] fix: remove wherever --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index facbc73c227..b9215efdac6 100644 --- a/package.json +++ b/package.json @@ -103,7 +103,7 @@ "@shapeshiftoss/hdwallet-metamask-multichain": "1.55.12", "@shapeshiftoss/hdwallet-native": "1.55.12", "@shapeshiftoss/hdwallet-native-vault": "1.55.12", - "@shapeshiftoss/hdwallet-phantom": "../hdwallet/packages/hdwallet-phantom", + "@shapeshiftoss/hdwallet-phantom": "1.55.12", "@shapeshiftoss/hdwallet-walletconnectv2": "1.55.12", "@shapeshiftoss/swapper": "workspace:^", "@shapeshiftoss/types": "workspace:^", diff --git a/yarn.lock b/yarn.lock index 996cd3c8a5c..f2b4532b81f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11451,9 +11451,9 @@ __metadata: languageName: node linkType: hard -"@shapeshiftoss/hdwallet-phantom@file:../hdwallet/packages/hdwallet-phantom::locator=%40shapeshiftoss%2Fweb%40workspace%3A.": +"@shapeshiftoss/hdwallet-phantom@npm:1.55.12": version: 1.55.12 - resolution: "@shapeshiftoss/hdwallet-phantom@file:../hdwallet/packages/hdwallet-phantom#../hdwallet/packages/hdwallet-phantom::hash=31dd14&locator=%40shapeshiftoss%2Fweb%40workspace%3A." + resolution: "@shapeshiftoss/hdwallet-phantom@npm:1.55.12" dependencies: "@shapeshiftoss/bitcoinjs-lib": 5.2.0-shapeshift.2 "@shapeshiftoss/hdwallet-core": 1.55.12 @@ -11462,7 +11462,7 @@ __metadata: bitcoinjs-message: ^2.0.0 ethers: 5.7.2 lodash: ^4.17.21 - checksum: 1e79337defbaee14298d6f51f4d79072881ac59199d07b11943bde1c53fdb579a7fd41bf39c3423e11679386f3228864b7343011ae99feb22de05df9d8367c44 + checksum: eeaffafd3ccfb06b08349b5f45a28d0ce2b2c3677b625ff2dea29dd148b637074875c523acf7595e353868f18f9425af304ea0643de240682bc8802efdb23911 languageName: node linkType: hard @@ -11682,7 +11682,7 @@ __metadata: "@shapeshiftoss/hdwallet-metamask-multichain": 1.55.12 "@shapeshiftoss/hdwallet-native": 1.55.12 "@shapeshiftoss/hdwallet-native-vault": 1.55.12 - "@shapeshiftoss/hdwallet-phantom": ../hdwallet/packages/hdwallet-phantom + "@shapeshiftoss/hdwallet-phantom": 1.55.12 "@shapeshiftoss/hdwallet-walletconnectv2": 1.55.12 "@shapeshiftoss/swapper": "workspace:^" "@shapeshiftoss/types": "workspace:^" From 04812951aa8e39d8f419bdfeecc901eb3ca22f66 Mon Sep 17 00:00:00 2001 From: NeOMakinG <14963751+NeOMakinG@users.noreply.github.com> Date: Tue, 19 Nov 2024 20:14:39 +0100 Subject: [PATCH 111/127] fix: continue --- .../src/solana/SolanaChainAdapter.ts | 90 ++++++++++--------- packages/chain-adapters/src/solana/types.ts | 2 - .../src/swappers/JupiterSwapper/endpoints.ts | 1 + 3 files changed, 47 insertions(+), 46 deletions(-) diff --git a/packages/chain-adapters/src/solana/SolanaChainAdapter.ts b/packages/chain-adapters/src/solana/SolanaChainAdapter.ts index c247694067c..c2c9c6b628f 100644 --- a/packages/chain-adapters/src/solana/SolanaChainAdapter.ts +++ b/packages/chain-adapters/src/solana/SolanaChainAdapter.ts @@ -6,7 +6,11 @@ import { solAssetId, toAssetId, } from '@shapeshiftoss/caip' -import type { SolanaSignTx, SolanaTxInstruction } from '@shapeshiftoss/hdwallet-core' +import type { + SolanaAddressLookupTableAccountInfo, + SolanaSignTx, + SolanaTxInstruction, +} from '@shapeshiftoss/hdwallet-core' import { supportsSolana } from '@shapeshiftoss/hdwallet-core' import type { BIP44Params } from '@shapeshiftoss/types' import { KnownChainIds } from '@shapeshiftoss/types' @@ -20,7 +24,7 @@ import { TokenAccountNotFoundError, TokenInvalidAccountOwnerError, } from '@solana/spl-token' -import type { TransactionInstruction } from '@solana/web3.js' +import type { AccountInfo, TransactionInstruction } from '@solana/web3.js' import { AddressLookupTableAccount, ComputeBudgetProgram, @@ -237,7 +241,7 @@ export class ChainAdapter implements IChainAdapter ) } - const addressLookupTableAccounts = await this.getAddressLookupTableAccounts( + const addressLookupTableAccountInfos = await this.getAddressLookupTableAccounts( chainSpecific.addressLookupTableAccounts ?? [], ) @@ -249,7 +253,7 @@ export class ChainAdapter implements IChainAdapter instructions, to: tokenId ? '' : to, value: tokenId ? '' : value, - addressLookupTableAccounts, + addressLookupTableAccountInfos, } return { txToSign } @@ -348,16 +352,6 @@ export class ChainAdapter implements IChainAdapter chainSpecific: { computeUnits, priorityFee: fast, - computeUnitsInstruction: this.convertInstruction( - ComputeBudgetProgram.setComputeUnitLimit({ - units: Number(computeUnits), - }), - ), - computeUnitsPriceInstruction: this.convertInstruction( - ComputeBudgetProgram.setComputeUnitPrice({ - microLamports: Number(fast), - }), - ), }, }, average: { @@ -368,16 +362,6 @@ export class ChainAdapter implements IChainAdapter chainSpecific: { computeUnits, priorityFee: average, - computeUnitsInstruction: this.convertInstruction( - ComputeBudgetProgram.setComputeUnitLimit({ - units: Number(computeUnits), - }), - ), - computeUnitsPriceInstruction: this.convertInstruction( - ComputeBudgetProgram.setComputeUnitPrice({ - microLamports: Number(average), - }), - ), }, }, slow: { @@ -388,16 +372,6 @@ export class ChainAdapter implements IChainAdapter chainSpecific: { computeUnits, priorityFee: slow, - computeUnitsInstruction: this.convertInstruction( - ComputeBudgetProgram.setComputeUnitLimit({ - units: Number(computeUnits), - }), - ), - computeUnitsPriceInstruction: this.convertInstruction( - ComputeBudgetProgram.setComputeUnitPrice({ - microLamports: Number(slow), - }), - ), }, }, } @@ -452,7 +426,9 @@ export class ChainAdapter implements IChainAdapter const { to, chainSpecific } = input const { from, tokenId, instructions = [] } = chainSpecific - const addressLookupTableAccounts = await this.getAddressLookupTableAccounts( + const estimationInstructions = [...instructions] + + const addressLookupTableAccounts = await this.getSolanaAddressLookupTableAccountsInfo( chainSpecific.addressLookupTableAccounts ?? [], ) @@ -470,9 +446,9 @@ export class ChainAdapter implements IChainAdapter value: input.value, }) - instructions.push(...tokenTransferInstructions) + estimationInstructions.push(...tokenTransferInstructions) } else { - instructions.push( + estimationInstructions.push( SystemProgram.transfer({ fromPubkey: new PublicKey(from), toPubkey: new PublicKey(to), @@ -484,14 +460,16 @@ export class ChainAdapter implements IChainAdapter // Set compute unit limit to the maximum compute units for the purposes of estimating the compute unit cost of a transaction, // ensuring the transaction does not exceed the maximum compute units alotted for a single transaction. - instructions.push(ComputeBudgetProgram.setComputeUnitLimit({ units: MAX_COMPUTE_UNITS })) + estimationInstructions.push( + ComputeBudgetProgram.setComputeUnitLimit({ units: MAX_COMPUTE_UNITS }), + ) // placeholder compute unit price instruction for the purposes of estimating the compute unit cost of a transaction - instructions.push(ComputeBudgetProgram.setComputeUnitPrice({ microLamports: 0 })) + estimationInstructions.push(ComputeBudgetProgram.setComputeUnitPrice({ microLamports: 0 })) const message = new TransactionMessage({ payerKey: new PublicKey(input.chainSpecific.from), - instructions, + instructions: estimationInstructions, // static block hash as fee estimation replaces the block hash with latest to save us a client side call recentBlockhash: '4sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZAMdL4VZHirAn', }).compileToV0Message(addressLookupTableAccounts) @@ -616,12 +594,16 @@ export class ChainAdapter implements IChainAdapter return this.providers.http } - public async getAddressLookupTableAccounts( + public async getAddressLookupTableAccountsInfo( + addresses: string[], + ): Promise<(AccountInfo | null)[]> { + return await this.connection.getMultipleAccountsInfo(addresses.map(key => new PublicKey(key))) + } + + public async getSolanaAddressLookupTableAccountsInfo( addresses: string[], ): Promise { - const addressLookupTableAccountInfos = await this.connection.getMultipleAccountsInfo( - addresses.map(key => new PublicKey(key)), - ) + const addressLookupTableAccountInfos = await this.getAddressLookupTableAccountsInfo(addresses) return addressLookupTableAccountInfos.reduce((acc, accountInfo, index) => { const addressLookupTableAddress = addresses[index] @@ -638,4 +620,24 @@ export class ChainAdapter implements IChainAdapter return acc }, new Array()) } + + public async getAddressLookupTableAccounts( + addresses: string[], + ): Promise { + const addressLookupTableAccountInfos = await this.getAddressLookupTableAccountsInfo(addresses) + console.log('test') + + return addressLookupTableAccountInfos.reduce((acc, accountInfo, index) => { + const addressLookupTableAddress = addresses[index] + if (accountInfo) { + const addressLookupTableAccount = { + key: addressLookupTableAddress, + data: Buffer.from(accountInfo.data), + } + acc.push(addressLookupTableAccount) + } + + return acc + }, new Array()) + } } diff --git a/packages/chain-adapters/src/solana/types.ts b/packages/chain-adapters/src/solana/types.ts index 22ee4bf222f..53101e7556f 100644 --- a/packages/chain-adapters/src/solana/types.ts +++ b/packages/chain-adapters/src/solana/types.ts @@ -38,8 +38,6 @@ export type GetFeeDataInput = { export type FeeData = { computeUnits: string priorityFee: string - computeUnitsInstruction: SolanaTxInstruction - computeUnitsPriceInstruction: SolanaTxInstruction } export type PriorityFeeData = { diff --git a/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts b/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts index 1b5e541584d..11fedd3899d 100644 --- a/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts +++ b/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts @@ -85,6 +85,7 @@ export const jupiterApi: SwapperApi = { ...swapResponse.setupInstructions.map(convertJupiterInstruction), convertJupiterInstruction(swapResponse.swapInstruction), ] + console.log({ instructions }, 'before creation') if (createTokenAccountInstruction) { instructions.unshift(createTokenAccountInstruction) From 0252a9e50eb06dff143fca1a97bcb6a2de764094 Mon Sep 17 00:00:00 2001 From: NeOMakinG <14963751+NeOMakinG@users.noreply.github.com> Date: Tue, 19 Nov 2024 21:54:17 +0100 Subject: [PATCH 112/127] fix: omg --- .../chain-adapters/src/solana/SolanaChainAdapter.ts | 12 +++++++++++- .../swapper/src/swappers/JupiterSwapper/endpoints.ts | 1 - 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/packages/chain-adapters/src/solana/SolanaChainAdapter.ts b/packages/chain-adapters/src/solana/SolanaChainAdapter.ts index c2c9c6b628f..e7f1eb4c1e7 100644 --- a/packages/chain-adapters/src/solana/SolanaChainAdapter.ts +++ b/packages/chain-adapters/src/solana/SolanaChainAdapter.ts @@ -21,6 +21,8 @@ import { createTransferInstruction, getAccount, getAssociatedTokenAddressSync, + TOKEN_2022_PROGRAM_ID, + TOKEN_PROGRAM_ID, TokenAccountNotFoundError, TokenInvalidAccountOwnerError, } from '@solana/spl-token' @@ -491,10 +493,18 @@ export class ChainAdapter implements IChainAdapter instruction?: TransactionInstruction destinationTokenAccount: PublicKey }> { + const accountInfo = await this.connection.getAccountInfo(new PublicKey(tokenId)) + + const TOKEN_PROGRAM = + accountInfo?.owner.toString() === TOKEN_2022_PROGRAM_ID.toString() + ? TOKEN_2022_PROGRAM_ID + : TOKEN_PROGRAM_ID + const destinationTokenAccount = getAssociatedTokenAddressSync( new PublicKey(tokenId), new PublicKey(to), true, + TOKEN_PROGRAM, ) // check if destination token account exists and add creation instruction if it doesn't @@ -512,6 +522,7 @@ export class ChainAdapter implements IChainAdapter destinationTokenAccount, new PublicKey(to), new PublicKey(tokenId), + TOKEN_PROGRAM, ), destinationTokenAccount, } @@ -625,7 +636,6 @@ export class ChainAdapter implements IChainAdapter addresses: string[], ): Promise { const addressLookupTableAccountInfos = await this.getAddressLookupTableAccountsInfo(addresses) - console.log('test') return addressLookupTableAccountInfos.reduce((acc, accountInfo, index) => { const addressLookupTableAddress = addresses[index] diff --git a/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts b/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts index 11fedd3899d..1b5e541584d 100644 --- a/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts +++ b/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts @@ -85,7 +85,6 @@ export const jupiterApi: SwapperApi = { ...swapResponse.setupInstructions.map(convertJupiterInstruction), convertJupiterInstruction(swapResponse.swapInstruction), ] - console.log({ instructions }, 'before creation') if (createTokenAccountInstruction) { instructions.unshift(createTokenAccountInstruction) From 957945ab6b899f6cfc493aad37f196423eecccc6 Mon Sep 17 00:00:00 2001 From: NeOMakinG <14963751+NeOMakinG@users.noreply.github.com> Date: Wed, 20 Nov 2024 14:32:46 +0100 Subject: [PATCH 113/127] fix: wouhouuuuu --- .../MultiHopTrade/hooks/useGetTradeQuotes/useGetTradeRates.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/components/MultiHopTrade/hooks/useGetTradeQuotes/useGetTradeRates.tsx b/src/components/MultiHopTrade/hooks/useGetTradeQuotes/useGetTradeRates.tsx index 15087e163de..fd782715f8d 100644 --- a/src/components/MultiHopTrade/hooks/useGetTradeQuotes/useGetTradeRates.tsx +++ b/src/components/MultiHopTrade/hooks/useGetTradeQuotes/useGetTradeRates.tsx @@ -224,6 +224,7 @@ export const useGetTradeRates = () => { allowMultiHop: true, affiliateBps, potentialAffiliateBps, + isManualReceiveAddress: Boolean(manualReceiveAddress), // Pass in the user's slippage preference if it's set, else let the swapper use its default slippageTolerancePercentageDecimal: userSlippageTolerancePercentageDecimal, pubKey: @@ -247,6 +248,7 @@ export const useGetTradeRates = () => { userSlippageTolerancePercentageDecimal, sellAssetUsdRate, sellAccountId, + manualReceiveAddress, isVotingPowerLoading, isBuyAssetChainSupported, receiveAddress, @@ -273,6 +275,7 @@ export const useGetTradeRates = () => { useGetSwapperTradeQuoteOrRate(getTradeQuoteArgs(SwapperName.Thorchain)) useGetSwapperTradeQuoteOrRate(getTradeQuoteArgs(SwapperName.Zrx)) useGetSwapperTradeQuoteOrRate(getTradeQuoteArgs(SwapperName.Chainflip)) + useGetSwapperTradeQuoteOrRate(getTradeQuoteArgs(SwapperName.Jupiter)) // true if any debounce, input or swapper is fetching const isAnyTradeQuoteLoading = useAppSelector(selectIsAnyTradeQuoteLoading) From 87894baaf5e45ce4976e2051e6b84184cd37edac Mon Sep 17 00:00:00 2001 From: NeOMakinG <14963751+NeOMakinG@users.noreply.github.com> Date: Wed, 20 Nov 2024 14:44:39 +0100 Subject: [PATCH 114/127] fix: to is not required --- packages/chain-adapters/src/solana/SolanaChainAdapter.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/chain-adapters/src/solana/SolanaChainAdapter.ts b/packages/chain-adapters/src/solana/SolanaChainAdapter.ts index e7f1eb4c1e7..2550bc0be07 100644 --- a/packages/chain-adapters/src/solana/SolanaChainAdapter.ts +++ b/packages/chain-adapters/src/solana/SolanaChainAdapter.ts @@ -434,7 +434,6 @@ export class ChainAdapter implements IChainAdapter chainSpecific.addressLookupTableAccounts ?? [], ) - if (!to) throw new Error(`${this.getName()}ChainAdapter: to is required`) if (!input.value) throw new Error(`${this.getName()}ChainAdapter: value is required`) const value = Number(input.value) From 5ac452c15c8a3e45a6a5f0d35388622a0437567a Mon Sep 17 00:00:00 2001 From: NeOMakinG <14963751+NeOMakinG@users.noreply.github.com> Date: Thu, 21 Nov 2024 10:00:14 +0100 Subject: [PATCH 115/127] fix: update hdwallet --- package.json | 24 ++++----- yarn.lock | 146 +++++++++++++++++++++++++-------------------------- 2 files changed, 85 insertions(+), 85 deletions(-) diff --git a/package.json b/package.json index 5af577f521d..3fdbe4f06de 100644 --- a/package.json +++ b/package.json @@ -93,18 +93,18 @@ "@shapeshiftoss/caip": "workspace:^", "@shapeshiftoss/chain-adapters": "workspace:^", "@shapeshiftoss/errors": "workspace:^", - "@shapeshiftoss/hdwallet-coinbase": "1.55.12", - "@shapeshiftoss/hdwallet-core": "1.55.12", - "@shapeshiftoss/hdwallet-keepkey": "1.55.12", - "@shapeshiftoss/hdwallet-keepkey-webusb": "1.55.12", - "@shapeshiftoss/hdwallet-keplr": "1.55.12", - "@shapeshiftoss/hdwallet-ledger": "1.55.12", - "@shapeshiftoss/hdwallet-ledger-webusb": "1.55.12", - "@shapeshiftoss/hdwallet-metamask-multichain": "1.55.12", - "@shapeshiftoss/hdwallet-native": "1.55.12", - "@shapeshiftoss/hdwallet-native-vault": "1.55.12", - "@shapeshiftoss/hdwallet-phantom": "1.55.12", - "@shapeshiftoss/hdwallet-walletconnectv2": "1.55.12", + "@shapeshiftoss/hdwallet-coinbase": "1.55.13", + "@shapeshiftoss/hdwallet-core": "1.55.13", + "@shapeshiftoss/hdwallet-keepkey": "1.55.13", + "@shapeshiftoss/hdwallet-keepkey-webusb": "1.55.13", + "@shapeshiftoss/hdwallet-keplr": "1.55.13", + "@shapeshiftoss/hdwallet-ledger": "1.55.13", + "@shapeshiftoss/hdwallet-ledger-webusb": "1.55.13", + "@shapeshiftoss/hdwallet-metamask-multichain": "1.55.13", + "@shapeshiftoss/hdwallet-native": "1.55.13", + "@shapeshiftoss/hdwallet-native-vault": "1.55.13", + "@shapeshiftoss/hdwallet-phantom": "1.55.13", + "@shapeshiftoss/hdwallet-walletconnectv2": "1.55.13", "@shapeshiftoss/swapper": "workspace:^", "@shapeshiftoss/types": "workspace:^", "@shapeshiftoss/unchained-client": "workspace:^", diff --git a/yarn.lock b/yarn.lock index 3815bd21b7b..a09c265bd2c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11236,15 +11236,15 @@ __metadata: languageName: node linkType: hard -"@shapeshiftoss/hdwallet-coinbase@npm:1.55.12": - version: 1.55.12 - resolution: "@shapeshiftoss/hdwallet-coinbase@npm:1.55.12" +"@shapeshiftoss/hdwallet-coinbase@npm:1.55.13": + version: 1.55.13 + resolution: "@shapeshiftoss/hdwallet-coinbase@npm:1.55.13" dependencies: "@coinbase/wallet-sdk": ^3.6.6 - "@shapeshiftoss/hdwallet-core": 1.55.12 + "@shapeshiftoss/hdwallet-core": 1.55.13 eth-rpc-errors: ^4.0.3 lodash: ^4.17.21 - checksum: 72a41e874b787b44fa3a9b5143f6f7c2d6caafaef090055f6332696534cea359fb253faea23dfcc72b43fbd24c0b8638328b4faf00b7954a9aac3202b9a7968f + checksum: 780e18d21737f89ea5c6c28ccaac94400e2cbffb641ecd0161b4ecf51d66fb5665daa7039d1cc6b0b213e55610c13d53302e1200ea7e51774cacf1be785b1aee languageName: node linkType: hard @@ -11274,9 +11274,9 @@ __metadata: languageName: node linkType: hard -"@shapeshiftoss/hdwallet-core@npm:1.55.12": - version: 1.55.12 - resolution: "@shapeshiftoss/hdwallet-core@npm:1.55.12" +"@shapeshiftoss/hdwallet-core@npm:1.55.13": + version: 1.55.13 + resolution: "@shapeshiftoss/hdwallet-core@npm:1.55.13" dependencies: "@shapeshiftoss/bitcoinjs-lib": 5.2.0-shapeshift.2 "@shapeshiftoss/proto-tx-builder": ^0.8.0 @@ -11286,30 +11286,30 @@ __metadata: lodash: ^4.17.21 rxjs: ^6.4.0 type-assertions: ^1.1.0 - checksum: ff0a70d045fcdc92cda161965e6ab3995d7fe441056368c7933bcf36b3e53a3e62a2be55fb339c1a5582899194738d0505684641f0606b66dbec60c588dc82e3 + checksum: 88a58a21feb9e2e50283fbb5e07b1d09bc418db80896d88092084a9f4155edb848d6bedf843f1e532449c4fe67e77b8845dc549d6c2fe126de86628849f9e257 languageName: node linkType: hard -"@shapeshiftoss/hdwallet-keepkey-webusb@npm:1.55.12": - version: 1.55.12 - resolution: "@shapeshiftoss/hdwallet-keepkey-webusb@npm:1.55.12" +"@shapeshiftoss/hdwallet-keepkey-webusb@npm:1.55.13": + version: 1.55.13 + resolution: "@shapeshiftoss/hdwallet-keepkey-webusb@npm:1.55.13" dependencies: - "@shapeshiftoss/hdwallet-core": 1.55.12 - "@shapeshiftoss/hdwallet-keepkey": 1.55.12 - checksum: 221378636cbdf7446e6cf37e7a833f8f0b11b118fe5964d1af348fa59da0aa85e58f6fe35171e7cac417ecfd8121044309f9e1706129252413be6306ee22a924 + "@shapeshiftoss/hdwallet-core": 1.55.13 + "@shapeshiftoss/hdwallet-keepkey": 1.55.13 + checksum: a49c4b328839354c6ca61c95155659a3255f0dc960f0bfb6b7534eea687f40c10a9abd058b99d5223c8a7f9a6dbeb2691997bf29478f658461346c43de180cb3 languageName: node linkType: hard -"@shapeshiftoss/hdwallet-keepkey@npm:1.55.12": - version: 1.55.12 - resolution: "@shapeshiftoss/hdwallet-keepkey@npm:1.55.12" +"@shapeshiftoss/hdwallet-keepkey@npm:1.55.13": + version: 1.55.13 + resolution: "@shapeshiftoss/hdwallet-keepkey@npm:1.55.13" dependencies: "@ethereumjs/common": ^2.4.0 "@ethereumjs/tx": ^3.3.0 "@keepkey/device-protocol": ^7.12.2 "@metamask/eth-sig-util": ^7.0.0 "@shapeshiftoss/bitcoinjs-lib": 5.2.0-shapeshift.2 - "@shapeshiftoss/hdwallet-core": 1.55.12 + "@shapeshiftoss/hdwallet-core": 1.55.13 "@shapeshiftoss/proto-tx-builder": ^0.8.0 bignumber.js: ^9.0.1 bnb-javascript-sdk-nobroadcast: ^2.16.14 @@ -11321,27 +11321,27 @@ __metadata: p-lazy: ^3.1.0 semver: ^7.3.8 tiny-secp256k1: ^1.1.6 - checksum: 75527761fee14364a1a6e3c6a3611683bda75940bab189788bb49c19b7b27c9ab8552dee033b92d29f3bcc22ef31d61fa5ec3b867c97fedde7666656110b0680 + checksum: df2df632f1644567678b7ad844f567de3bf7629a2c80c3f28558271e5727fb142c88520d6328685a32d54cf520c444860acd85c2cd17588a41193d0a5f47c4a9 languageName: node linkType: hard -"@shapeshiftoss/hdwallet-keplr@npm:1.55.12": - version: 1.55.12 - resolution: "@shapeshiftoss/hdwallet-keplr@npm:1.55.12" +"@shapeshiftoss/hdwallet-keplr@npm:1.55.13": + version: 1.55.13 + resolution: "@shapeshiftoss/hdwallet-keplr@npm:1.55.13" dependencies: "@shapeshiftoss/caip": 8.15.0 - "@shapeshiftoss/hdwallet-core": 1.55.12 + "@shapeshiftoss/hdwallet-core": 1.55.13 "@shapeshiftoss/proto-tx-builder": ^0.8.0 "@shapeshiftoss/types": 3.1.3 base64-js: ^1.5.1 lodash: ^4.17.21 - checksum: 42a8d8a55768714d2dbe3795af7fbb593b7e0a26cdb0e54fae6a0902c18cf404cd85afd47819b65f6f9c26af6dabf6973c72a5f4bf301dddc140a5c74210c6e5 + checksum: 11a32c9dd62274427700d1411157b5f4c67a86ac79b20b69e1cf71aab51c8968c031624912545391a0f71ffe651b38092fdafbaed6b7ef9270e09e78e7e6a156 languageName: node linkType: hard -"@shapeshiftoss/hdwallet-ledger-webusb@npm:1.55.12": - version: 1.55.12 - resolution: "@shapeshiftoss/hdwallet-ledger-webusb@npm:1.55.12" +"@shapeshiftoss/hdwallet-ledger-webusb@npm:1.55.13": + version: 1.55.13 + resolution: "@shapeshiftoss/hdwallet-ledger-webusb@npm:1.55.13" dependencies: "@ledgerhq/hw-app-btc": ^10.4.1 "@ledgerhq/hw-app-eth": ^6.38.0 @@ -11349,23 +11349,23 @@ __metadata: "@ledgerhq/hw-transport-webusb": ^6.29.2 "@ledgerhq/live-common": ^21.8.2 "@ledgerhq/logs": ^6.10.1 - "@shapeshiftoss/hdwallet-core": 1.55.12 - "@shapeshiftoss/hdwallet-ledger": 1.55.12 + "@shapeshiftoss/hdwallet-core": 1.55.13 + "@shapeshiftoss/hdwallet-ledger": 1.55.13 "@types/w3c-web-usb": ^1.0.4 p-queue: ^7.4.1 - checksum: d15975e5cbf814bcf0566cd906eff163d6c4bb92f77ce359b89d87447745b5a5bbccb1677c40e5175468e6668e99b7db39a867c560cd37236a0220bd1265d343 + checksum: 7bf2c50f1c86d4994a80f4792a7d4cde9ef880f5b77b20a7b198908c178a15e10490cf9d99e065df456f68b07c5a522db63a88c5acb849ab65df184c43d6b13b languageName: node linkType: hard -"@shapeshiftoss/hdwallet-ledger@npm:1.55.12": - version: 1.55.12 - resolution: "@shapeshiftoss/hdwallet-ledger@npm:1.55.12" +"@shapeshiftoss/hdwallet-ledger@npm:1.55.13": + version: 1.55.13 + resolution: "@shapeshiftoss/hdwallet-ledger@npm:1.55.13" dependencies: "@ethereumjs/common": ^2.4.0 "@ethereumjs/tx": ^3.3.0 "@ledgerhq/hw-app-cosmos": ^6.29.1 "@shapeshiftoss/bitcoinjs-lib": 5.2.0-shapeshift.2 - "@shapeshiftoss/hdwallet-core": 1.55.12 + "@shapeshiftoss/hdwallet-core": 1.55.13 base64-js: ^1.5.1 bchaddrjs: ^0.4.4 bitcoinjs-message: ^2.0.0 @@ -11373,32 +11373,32 @@ __metadata: ethereumjs-tx: 1.3.7 ethereumjs-util: ^6.1.0 lodash: ^4.17.21 - checksum: 45a7ddff72e19fa68ec7207b0155cea7ab5f90e2c667ac769b76221a0aa46261dda25bc0520762d2ec574289d028e7dba04c3fa1949ee089679a8385f1044496 + checksum: 9aca320bc95367bed091f56f3c908177b9e9ed9cb0a51655820d82d9478e5a67165309de4abdc7494eca23f9d14ad061c4717ecab407cde3df65aff5d80a9e07 languageName: node linkType: hard -"@shapeshiftoss/hdwallet-metamask-multichain@npm:1.55.12": - version: 1.55.12 - resolution: "@shapeshiftoss/hdwallet-metamask-multichain@npm:1.55.12" +"@shapeshiftoss/hdwallet-metamask-multichain@npm:1.55.13": + version: 1.55.13 + resolution: "@shapeshiftoss/hdwallet-metamask-multichain@npm:1.55.13" dependencies: "@metamask/detect-provider": ^1.2.0 "@metamask/onboarding": ^1.0.1 "@shapeshiftoss/common-api": ^9.3.0 - "@shapeshiftoss/hdwallet-core": 1.55.12 + "@shapeshiftoss/hdwallet-core": 1.55.13 "@shapeshiftoss/metamask-snaps-adapter": ^1.0.12 "@shapeshiftoss/metamask-snaps-types": ^1.0.12 eth-rpc-errors: ^4.0.3 lodash: ^4.17.21 mipd: ^0.0.7 - checksum: 47da1cf651eb3b7827df0b78d1870c9f37356b8eba5144d88532a89b132b7860a269460fb07b49cf1d17fbf2d8b9914189d3d120ddaede7a5fd12db44ce87557 + checksum: 0845f532da720a34934067c7940e7974f7e113ca7224ae612fbbe711fbf5acdee14eab20e6ed3c0d236c35295d2458e6c9d9d111ac9817bb816a3c5e9a0b3af1 languageName: node linkType: hard -"@shapeshiftoss/hdwallet-native-vault@npm:1.55.12": - version: 1.55.12 - resolution: "@shapeshiftoss/hdwallet-native-vault@npm:1.55.12" +"@shapeshiftoss/hdwallet-native-vault@npm:1.55.13": + version: 1.55.13 + resolution: "@shapeshiftoss/hdwallet-native-vault@npm:1.55.13" dependencies: - "@shapeshiftoss/hdwallet-native": 1.55.12 + "@shapeshiftoss/hdwallet-native": 1.55.13 bip39: ^3.0.4 hash-wasm: ^4.11.0 idb-keyval: ^6.0.3 @@ -11407,17 +11407,17 @@ __metadata: type-assertions: ^1.1.0 uuid: ^8.3.2 web-encoding: ^1.1.0 - checksum: d6b90d256eddb2e4a7ff1b0f872c42574dcd3b6d620779e591b8634621c2760d7dee2d82d9456d04cb25b5e64c2b8eeeea7e0cceadc316086707a8d6766e6fe9 + checksum: 346f5564e237cb250ce506569fbdaa19a5bb87911b48c328e64137f7070b68503e0206f7b1716c4a9b6d9c31216b14fcdaf94834c61ab0c29a79939d8f611d9c languageName: node linkType: hard -"@shapeshiftoss/hdwallet-native@npm:1.55.12": - version: 1.55.12 - resolution: "@shapeshiftoss/hdwallet-native@npm:1.55.12" +"@shapeshiftoss/hdwallet-native@npm:1.55.13": + version: 1.55.13 + resolution: "@shapeshiftoss/hdwallet-native@npm:1.55.13" dependencies: "@shapeshiftoss/bitcoinjs-lib": 5.2.0-shapeshift.2 "@shapeshiftoss/fiosdk": 1.2.1-shapeshift.6 - "@shapeshiftoss/hdwallet-core": 1.55.12 + "@shapeshiftoss/hdwallet-core": 1.55.13 "@shapeshiftoss/proto-tx-builder": ^0.8.0 "@zxing/text-encoding": ^0.9.0 bchaddrjs: ^0.4.9 @@ -11439,7 +11439,7 @@ __metadata: tendermint-tx-builder: ^1.0.9 tiny-secp256k1: ^1.1.6 web-encoding: ^1.1.0 - checksum: da2ae7c9319875a25c14e7df3bff8e13aa18f48508df6337ea4cb24a5a8ad183a3f07c8c65831dd6f2a4029719393c6d7fcacfa2188d6176b547baa8adcc4126 + checksum: 61489ee2c49d1625f9d2d7949a62f4a82a1f0d546b0878efb17677372d035a10dae8c1bf1931e8c49b849d41d62231ecd630496e50346a3646e6db79c666da2e languageName: node linkType: hard @@ -11475,30 +11475,30 @@ __metadata: languageName: node linkType: hard -"@shapeshiftoss/hdwallet-phantom@npm:1.55.12": - version: 1.55.12 - resolution: "@shapeshiftoss/hdwallet-phantom@npm:1.55.12" +"@shapeshiftoss/hdwallet-phantom@npm:1.55.13": + version: 1.55.13 + resolution: "@shapeshiftoss/hdwallet-phantom@npm:1.55.13" dependencies: "@shapeshiftoss/bitcoinjs-lib": 5.2.0-shapeshift.2 - "@shapeshiftoss/hdwallet-core": 1.55.12 + "@shapeshiftoss/hdwallet-core": 1.55.13 "@solana/web3.js": ^1.95.3 base64-js: ^1.5.1 bitcoinjs-message: ^2.0.0 ethers: 5.7.2 lodash: ^4.17.21 - checksum: eeaffafd3ccfb06b08349b5f45a28d0ce2b2c3677b625ff2dea29dd148b637074875c523acf7595e353868f18f9425af304ea0643de240682bc8802efdb23911 + checksum: 6ad9dd9c6a1290d7c49f8084b2546887519e333b54b91c981a18193d31c37e2ddf582934b9dbc21eb80d8b266d66ea3969a432050f0eb97959809e854f066b98 languageName: node linkType: hard -"@shapeshiftoss/hdwallet-walletconnectv2@npm:1.55.12": - version: 1.55.12 - resolution: "@shapeshiftoss/hdwallet-walletconnectv2@npm:1.55.12" +"@shapeshiftoss/hdwallet-walletconnectv2@npm:1.55.13": + version: 1.55.13 + resolution: "@shapeshiftoss/hdwallet-walletconnectv2@npm:1.55.13" dependencies: - "@shapeshiftoss/hdwallet-core": 1.55.12 + "@shapeshiftoss/hdwallet-core": 1.55.13 "@walletconnect/ethereum-provider": ^2.10.1 "@walletconnect/modal": ^2.6.2 ethers: ^5.6.5 - checksum: 8ccf0f41758969b764444ba6c69ee27d699bfca885bca350e1493d98f4f50232be548fe1fa2938e7a5e225a88dd94f9728c9ab0744b70c77439aef73cd43b897 + checksum: f954c50e0154dca4ec663c97c6699d78f2bdc94bebc924f43c4d15d8e56f5716d259066d331493431b46269a9093e48ba421ca0a70c33b2b36f7a8fe230015de languageName: node linkType: hard @@ -11696,18 +11696,18 @@ __metadata: "@shapeshiftoss/caip": "workspace:^" "@shapeshiftoss/chain-adapters": "workspace:^" "@shapeshiftoss/errors": "workspace:^" - "@shapeshiftoss/hdwallet-coinbase": 1.55.12 - "@shapeshiftoss/hdwallet-core": 1.55.12 - "@shapeshiftoss/hdwallet-keepkey": 1.55.12 - "@shapeshiftoss/hdwallet-keepkey-webusb": 1.55.12 - "@shapeshiftoss/hdwallet-keplr": 1.55.12 - "@shapeshiftoss/hdwallet-ledger": 1.55.12 - "@shapeshiftoss/hdwallet-ledger-webusb": 1.55.12 - "@shapeshiftoss/hdwallet-metamask-multichain": 1.55.12 - "@shapeshiftoss/hdwallet-native": 1.55.12 - "@shapeshiftoss/hdwallet-native-vault": 1.55.12 - "@shapeshiftoss/hdwallet-phantom": 1.55.12 - "@shapeshiftoss/hdwallet-walletconnectv2": 1.55.12 + "@shapeshiftoss/hdwallet-coinbase": 1.55.13 + "@shapeshiftoss/hdwallet-core": 1.55.13 + "@shapeshiftoss/hdwallet-keepkey": 1.55.13 + "@shapeshiftoss/hdwallet-keepkey-webusb": 1.55.13 + "@shapeshiftoss/hdwallet-keplr": 1.55.13 + "@shapeshiftoss/hdwallet-ledger": 1.55.13 + "@shapeshiftoss/hdwallet-ledger-webusb": 1.55.13 + "@shapeshiftoss/hdwallet-metamask-multichain": 1.55.13 + "@shapeshiftoss/hdwallet-native": 1.55.13 + "@shapeshiftoss/hdwallet-native-vault": 1.55.13 + "@shapeshiftoss/hdwallet-phantom": 1.55.13 + "@shapeshiftoss/hdwallet-walletconnectv2": 1.55.13 "@shapeshiftoss/swapper": "workspace:^" "@shapeshiftoss/types": "workspace:^" "@shapeshiftoss/unchained-client": "workspace:^" From e4891d6256da07fae14a9f7eaa0e89ba7aefbe0d Mon Sep 17 00:00:00 2001 From: NeOMakinG <14963751+NeOMakinG@users.noreply.github.com> Date: Fri, 22 Nov 2024 11:28:39 +0100 Subject: [PATCH 116/127] fix: review feedbacks --- .env.base | 7 ++----- .env.dev | 4 ++-- .env.develop | 2 +- .../src/solana/SolanaChainAdapter.ts | 2 +- packages/chain-adapters/src/utils/index.ts | 2 +- packages/chain-adapters/src/utils/solanaUtils.ts | 9 --------- packages/chain-adapters/src/utils/svmUtils.ts | 9 +++++++++ .../ChainflipSwapper/swapperApi/getTradeQuote.ts | 2 +- .../src/swappers/JupiterSwapper/JupiterSwapper.ts | 5 ++--- .../swapper/src/swappers/JupiterSwapper/types.ts | 3 --- .../src/swappers/JupiterSwapper/utils/constants.ts | 6 +++--- .../src/swappers/JupiterSwapper/utils/helpers.ts | 8 +++----- .../JupiterSwapper/utils/jupiterService.ts | 4 ++-- .../filterBuyAssetsBySellAssetId.ts | 8 +++----- packages/swapper/src/types.ts | 2 +- packages/types/src/base.ts | 2 +- react-app-rewired/headers/csps/jupiter.ts | 3 ++- src/config.ts | 9 +++++---- src/constants/urls.ts | 2 ++ src/state/helpers.ts | 13 +++++++------ .../slices/preferencesSlice/preferencesSlice.ts | 14 +++++++------- src/test/mocks/store.ts | 6 +++--- 22 files changed, 58 insertions(+), 64 deletions(-) delete mode 100644 packages/chain-adapters/src/utils/solanaUtils.ts create mode 100644 packages/chain-adapters/src/utils/svmUtils.ts delete mode 100644 packages/swapper/src/swappers/JupiterSwapper/types.ts create mode 100644 src/constants/urls.ts diff --git a/.env.base b/.env.base index 00bce8b135b..fdd9a9bf9d1 100644 --- a/.env.base +++ b/.env.base @@ -61,14 +61,14 @@ REACT_APP_FEATURE_DYNAMIC_LP_ASSETS=false REACT_APP_FEATURE_READ_ONLY_ASSETS=true # swapper feature flags - other .env files will override these -REACT_APP_FEATURE_CHAINFLIP=false +REACT_APP_FEATURE_CHAINFLIP_SWAP=false REACT_APP_FEATURE_CHAINFLIP_DCA=false REACT_APP_FEATURE_COWSWAP=true REACT_APP_FEATURE_LIFI_SWAP=true REACT_APP_FEATURE_THOR_SWAP=true REACT_APP_FEATURE_THOR_SWAP_STREAMING_SWAPS=true REACT_APP_FEATURE_ZRX_SWAP=true -REACT_APP_FEATURE_JUPITER=false +REACT_APP_FEATURE_JUPITER_SWAP=false # chat woot REACT_APP_CHATWOOT_TOKEN=jmoXp9BPMSPEYHeJX5YKT15Q @@ -178,6 +178,3 @@ REACT_APP_ZRX_BASE_URL=https://api.proxy.shapeshift.com/api/v1/zrx/ # chainflip REACT_APP_CHAINFLIP_API_KEY=6ba154d4-e219-472a-9674-5fa5b1300ccf REACT_APP_CHAINFLIP_API_URL=https://chainflip-broker.io - -# jupiter -REACT_APP_JUPITER_API_URL=https://quote-api.jup.ag/v6 diff --git a/.env.dev b/.env.dev index cbc7d7610e7..5021c9462ce 100644 --- a/.env.dev +++ b/.env.dev @@ -1,9 +1,9 @@ # feature flags -REACT_APP_FEATURE_CHAINFLIP=true +REACT_APP_FEATURE_CHAINFLIP_SWAP=true REACT_APP_FEATURE_CHAINFLIP_DCA=false REACT_APP_FEATURE_PUBLIC_TRADE_ROUTE=false REACT_APP_FEATURE_LIMIT_ORDERS=true -REACT_APP_FEATURE_JUPITER=true +REACT_APP_FEATURE_JUPITER_SWAP=true # logging REACT_APP_REDUX_WINDOW=false diff --git a/.env.develop b/.env.develop index 96805f113b0..511edd77407 100644 --- a/.env.develop +++ b/.env.develop @@ -1,7 +1,7 @@ # feature flags REACT_APP_FEATURE_LIMIT_ORDERS=true REACT_APP_FEATURE_PUBLIC_TRADE_ROUTE=false -REACT_APP_FEATURE_CHAINFLIP=true +REACT_APP_FEATURE_CHAINFLIP_SWAP=true REACT_APP_FEATURE_CHAINFLIP_DCA=false # mixpanel diff --git a/packages/chain-adapters/src/solana/SolanaChainAdapter.ts b/packages/chain-adapters/src/solana/SolanaChainAdapter.ts index 2550bc0be07..dfe52abd917 100644 --- a/packages/chain-adapters/src/solana/SolanaChainAdapter.ts +++ b/packages/chain-adapters/src/solana/SolanaChainAdapter.ts @@ -64,7 +64,7 @@ import { toAddressNList, toRootDerivationPath } from '../utils' import { assertAddressNotSanctioned } from '../utils/validateAddress' import { microLamportsToLamports } from './utils' -export const solanaChainIds = [KnownChainIds.SolanaMainnet] as const +export const svmChainIds = [KnownChainIds.SolanaMainnet] as const // Maximum compute units allowed for a single solana transaction const MAX_COMPUTE_UNITS = 1400000 diff --git a/packages/chain-adapters/src/utils/index.ts b/packages/chain-adapters/src/utils/index.ts index edb9a532ea1..4537818a8df 100644 --- a/packages/chain-adapters/src/utils/index.ts +++ b/packages/chain-adapters/src/utils/index.ts @@ -5,7 +5,7 @@ export * from './bignumber' export * from './bip44' export * from './fees' export * from './utxoUtils' -export * from './solanaUtils' +export * from './svmUtils' export * from './ledgerAppGate' export const getAssetNamespace = (type: string): AssetNamespace => { diff --git a/packages/chain-adapters/src/utils/solanaUtils.ts b/packages/chain-adapters/src/utils/solanaUtils.ts deleted file mode 100644 index b2fd2ecde01..00000000000 --- a/packages/chain-adapters/src/utils/solanaUtils.ts +++ /dev/null @@ -1,9 +0,0 @@ -import type { SolanaChainId } from '@shapeshiftoss/types' - -import { solanaChainIds } from '../solana/SolanaChainAdapter' - -export const isSolanaChainId = ( - maybeSolanaChainId: string | SolanaChainId, -): maybeSolanaChainId is SolanaChainId => { - return solanaChainIds.includes(maybeSolanaChainId as SolanaChainId) -} diff --git a/packages/chain-adapters/src/utils/svmUtils.ts b/packages/chain-adapters/src/utils/svmUtils.ts new file mode 100644 index 00000000000..e525a2be3b0 --- /dev/null +++ b/packages/chain-adapters/src/utils/svmUtils.ts @@ -0,0 +1,9 @@ +import type { SvmChainId } from '@shapeshiftoss/types' + +import { svmChainIds } from '../solana/SolanaChainAdapter' + +export const isSvmChainId = ( + maybeSvmChainId: string | SvmChainId, +): maybeSvmChainId is SvmChainId => { + return svmChainIds.includes(maybeSvmChainId as SvmChainId) +} diff --git a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts index 28f3cfecbdf..ab9d371e9ed 100644 --- a/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts +++ b/packages/swapper/src/swappers/ChainflipSwapper/swapperApi/getTradeQuote.ts @@ -253,7 +253,7 @@ export const _getTradeQuote = async ( const isStreaming = singleQuoteResponse.type === CHAINFLIP_DCA_QUOTE const feeData = await getFeeData() - if (isStreaming && !deps.config.REACT_APP_FEATURE_CHAINFLIP_DCA) { + if (isStreaming && !deps.config.REACT_APP_FEATURE_CHAINFLIP_SWAP_DCA) { // DCA currently disabled - Streaming swap logic is very much tied to THOR currently and will deserve its own PR to generalize // Even if we manage to get DCA swaps to execute, we wouldn't manage to properly poll with current web THOR-centric arch continue diff --git a/packages/swapper/src/swappers/JupiterSwapper/JupiterSwapper.ts b/packages/swapper/src/swappers/JupiterSwapper/JupiterSwapper.ts index 8219f24812a..12c4b2c8845 100644 --- a/packages/swapper/src/swappers/JupiterSwapper/JupiterSwapper.ts +++ b/packages/swapper/src/swappers/JupiterSwapper/JupiterSwapper.ts @@ -4,7 +4,6 @@ import type { Asset } from '@shapeshiftoss/types' import { executeSolanaTransaction } from '../..' import type { BuyAssetBySellIdInput, Swapper } from '../../types' import { filterSameChainSolanaBuyAssetsBySellAssetId } from '../utils/filterBuyAssetsBySellAssetId/filterBuyAssetsBySellAssetId' -import type { JupiterSupportedChainId } from './types' import { jupiterSupportedChainIds } from './utils/constants' export const jupiterSwapper: Swapper = { @@ -15,7 +14,7 @@ export const jupiterSwapper: Swapper = { assets .filter(asset => { const { chainId } = asset - return jupiterSupportedChainIds.includes(chainId as JupiterSupportedChainId) + return jupiterSupportedChainIds.includes(chainId) }) .map(asset => asset.assetId), ) @@ -26,7 +25,7 @@ export const jupiterSwapper: Swapper = { filterSameChainSolanaBuyAssetsBySellAssetId(input) .filter(asset => { const { chainId } = asset - return jupiterSupportedChainIds.includes(chainId as JupiterSupportedChainId) + return jupiterSupportedChainIds.includes(chainId) }) .map(asset => asset.assetId), ) diff --git a/packages/swapper/src/swappers/JupiterSwapper/types.ts b/packages/swapper/src/swappers/JupiterSwapper/types.ts deleted file mode 100644 index bd5d56e59ec..00000000000 --- a/packages/swapper/src/swappers/JupiterSwapper/types.ts +++ /dev/null @@ -1,3 +0,0 @@ -import type { jupiterSupportedChainIds } from './utils/constants' - -export type JupiterSupportedChainId = (typeof jupiterSupportedChainIds)[number] diff --git a/packages/swapper/src/swappers/JupiterSwapper/utils/constants.ts b/packages/swapper/src/swappers/JupiterSwapper/utils/constants.ts index b6437d50c86..f9c97ecbfd9 100644 --- a/packages/swapper/src/swappers/JupiterSwapper/utils/constants.ts +++ b/packages/swapper/src/swappers/JupiterSwapper/utils/constants.ts @@ -3,9 +3,9 @@ import { KnownChainIds } from '@shapeshiftoss/types' import type { SupportedChainIds } from '../../../types' -export const jupiterSupportedChainIds = [KnownChainIds.SolanaMainnet] as const +export const jupiterSupportedChainIds = [KnownChainIds.SolanaMainnet] as ChainId[] export const JUPITER_SUPPORTED_CHAIN_IDS: SupportedChainIds = { - sell: jupiterSupportedChainIds as unknown as ChainId[], - buy: jupiterSupportedChainIds as unknown as ChainId[], + sell: jupiterSupportedChainIds, + buy: jupiterSupportedChainIds, } diff --git a/packages/swapper/src/swappers/JupiterSwapper/utils/helpers.ts b/packages/swapper/src/swappers/JupiterSwapper/utils/helpers.ts index 35f2f1629f9..1ba0fcce6e3 100644 --- a/packages/swapper/src/swappers/JupiterSwapper/utils/helpers.ts +++ b/packages/swapper/src/swappers/JupiterSwapper/utils/helpers.ts @@ -5,18 +5,15 @@ import type { AxiosResponse } from 'axios' import type { SwapErrorRight } from '../../../types' import type { QuoteResponse } from '../models/QuoteResponse' import type { SwapInstructionsResponse } from '../models/SwapInstructionsResponse' -import type { JupiterSupportedChainId } from '../types' import { jupiterSupportedChainIds } from './constants' import { jupiterService } from './jupiterService' -export const isSupportedChainId = (chainId: ChainId): chainId is JupiterSupportedChainId => { - return jupiterSupportedChainIds.includes(chainId as JupiterSupportedChainId) +export const isSupportedChainId = (chainId: ChainId): chainId is ChainId => { + return jupiterSupportedChainIds.includes(chainId) } const JUPITER_TRANSACTION_MAX_ACCOUNTS = 54 -// const SHAPESHIFT_SOLANA_FEE_ACCOUNT = 'C7RTJbss7R1r7j8NUNYbasUXfbPJR99PMhqznvCiU43N' - type GetJupiterQuoteArgs = { apiUrl: string sourceAsset: string @@ -53,6 +50,7 @@ export const getJupiterQuote = ({ `&platformFeeBps=${commissionBps}`, ) +// @TODO: Add DAO's fee account export const getJupiterSwapInstructions = ({ apiUrl, fromAddress, diff --git a/packages/swapper/src/swappers/JupiterSwapper/utils/jupiterService.ts b/packages/swapper/src/swappers/JupiterSwapper/utils/jupiterService.ts index f4b2102b3e5..206f0968015 100644 --- a/packages/swapper/src/swappers/JupiterSwapper/utils/jupiterService.ts +++ b/packages/swapper/src/swappers/JupiterSwapper/utils/jupiterService.ts @@ -1,7 +1,7 @@ import { SwapperName } from '../../../types' import { createCache, makeSwapperAxiosServiceMonadic } from '../../../utils' -const maxAge = 15 * 1000 // 15 seconds ttl for all except cached to get fresh status updates +const maxAgeMillis = 15 * 1000 // 15 seconds ttl for all except cached to get fresh status updates const cachedUrls: string[] = [] const axiosConfig = { @@ -12,7 +12,7 @@ const axiosConfig = { }, } -const jupiterServiceBase = createCache(maxAge, cachedUrls, axiosConfig) +const jupiterServiceBase = createCache(maxAgeMillis, cachedUrls, axiosConfig) export const jupiterService = makeSwapperAxiosServiceMonadic( jupiterServiceBase, diff --git a/packages/swapper/src/swappers/utils/filterBuyAssetsBySellAssetId/filterBuyAssetsBySellAssetId.ts b/packages/swapper/src/swappers/utils/filterBuyAssetsBySellAssetId/filterBuyAssetsBySellAssetId.ts index 5dfd0df7be0..c9689a29659 100644 --- a/packages/swapper/src/swappers/utils/filterBuyAssetsBySellAssetId/filterBuyAssetsBySellAssetId.ts +++ b/packages/swapper/src/swappers/utils/filterBuyAssetsBySellAssetId/filterBuyAssetsBySellAssetId.ts @@ -1,5 +1,5 @@ import { arbitrumNovaChainId, type ChainId } from '@shapeshiftoss/caip' -import { isEvmChainId, isSolanaChainId } from '@shapeshiftoss/chain-adapters' +import { isEvmChainId, isSvmChainId } from '@shapeshiftoss/chain-adapters' import type { Asset } from '@shapeshiftoss/types' import type { BuyAssetBySellIdInput } from '../../../types' @@ -28,13 +28,11 @@ const _filterSolanaBuyAssetsBySellAssetId = ( chainIdPredicate: ChainIdPredicate, ): Asset[] => { // evm only - if (!isSolanaChainId(sellAsset.chainId)) return [] + if (!isSvmChainId(sellAsset.chainId)) return [] return assets.filter(buyAsset => { // evm only AND chain id predicate with no arbitrum nova support for any swappers - return ( - isSolanaChainId(buyAsset.chainId) && chainIdPredicate(buyAsset.chainId, sellAsset.chainId) - ) + return isSvmChainId(buyAsset.chainId) && chainIdPredicate(buyAsset.chainId, sellAsset.chainId) }) } diff --git a/packages/swapper/src/types.ts b/packages/swapper/src/types.ts index c1257fe3008..e926cd99e6f 100644 --- a/packages/swapper/src/types.ts +++ b/packages/swapper/src/types.ts @@ -51,7 +51,7 @@ export type SwapperConfig = { REACT_APP_ZRX_BASE_URL: string REACT_APP_CHAINFLIP_API_KEY: string REACT_APP_CHAINFLIP_API_URL: string - REACT_APP_FEATURE_CHAINFLIP_DCA: boolean + REACT_APP_FEATURE_CHAINFLIP_SWAP_DCA: boolean REACT_APP_JUPITER_API_URL: string } diff --git a/packages/types/src/base.ts b/packages/types/src/base.ts index 0988b493035..b872606f016 100644 --- a/packages/types/src/base.ts +++ b/packages/types/src/base.ts @@ -48,7 +48,7 @@ export type UtxoChainId = | KnownChainIds.DogecoinMainnet | KnownChainIds.LitecoinMainnet -export type SolanaChainId = KnownChainIds.SolanaMainnet +export type SvmChainId = KnownChainIds.SolanaMainnet export enum WithdrawType { DELAYED, diff --git a/react-app-rewired/headers/csps/jupiter.ts b/react-app-rewired/headers/csps/jupiter.ts index a7947c636be..d6d9d705cc4 100644 --- a/react-app-rewired/headers/csps/jupiter.ts +++ b/react-app-rewired/headers/csps/jupiter.ts @@ -1,5 +1,6 @@ +import { JUPITER_BASE_API_URL } from '../../../src/constants/urls' import type { Csp } from '../types' export const csp: Csp = { - 'connect-src': ['https://quote-api.jup.ag/'], + 'connect-src': [JUPITER_BASE_API_URL], } diff --git a/src/config.ts b/src/config.ts index 41c5634396f..a18ac54eefe 100644 --- a/src/config.ts +++ b/src/config.ts @@ -1,3 +1,4 @@ +import { JUPITER_API_URL } from 'constants/urls' import * as envalid from 'envalid' import { bool } from 'envalid' import forEach from 'lodash/forEach' @@ -174,14 +175,14 @@ const validators = { REACT_APP_FEATURE_FOX_PAGE_GOVERNANCE: bool({ default: false }), REACT_APP_FEATURE_LIMIT_ORDERS: bool({ default: false }), REACT_APP_ZRX_BASE_URL: url(), - REACT_APP_FEATURE_CHAINFLIP: bool({ default: false }), - REACT_APP_FEATURE_CHAINFLIP_DCA: bool({ default: false }), + REACT_APP_FEATURE_CHAINFLIP_SWAP: bool({ default: false }), + REACT_APP_FEATURE_CHAINFLIP_SWAP_DCA: bool({ default: false }), REACT_APP_CHAINFLIP_API_KEY: str(), REACT_APP_CHAINFLIP_API_URL: url(), REACT_APP_FEATURE_PUBLIC_TRADE_ROUTE: bool({ default: false }), REACT_APP_FEATURE_THOR_FREE_FEES: bool({ default: false }), - REACT_APP_FEATURE_JUPITER: bool({ default: false }), - REACT_APP_JUPITER_API_URL: url(), + REACT_APP_FEATURE_JUPITER_SWAP: bool({ default: false }), + REACT_APP_JUPITER_API_URL: url({ default: JUPITER_API_URL }), } function reporter({ errors }: envalid.ReporterOptions) { diff --git a/src/constants/urls.ts b/src/constants/urls.ts new file mode 100644 index 00000000000..650668c44bd --- /dev/null +++ b/src/constants/urls.ts @@ -0,0 +1,2 @@ +export const JUPITER_BASE_API_URL = 'https://quote-api.jup.ag' +export const JUPITER_API_URL = `${JUPITER_BASE_API_URL}/v6` diff --git a/src/state/helpers.ts b/src/state/helpers.ts index 72cac831b26..ec53402e389 100644 --- a/src/state/helpers.ts +++ b/src/state/helpers.ts @@ -24,14 +24,14 @@ export const isCrossAccountTradeSupported = (swapperName: SwapperName) => { export const getEnabledSwappers = ( { - Chainflip, - Portals, + ChainflipSwap, + PortalsSwap, LifiSwap, ThorSwap, ZrxSwap, ArbitrumBridge, Cowswap, - Jupiter, + JupiterSwap, }: FeatureFlags, isCrossAccountTrade: boolean, ): Record => { @@ -48,11 +48,12 @@ export const getEnabledSwappers = ( ArbitrumBridge && (!isCrossAccountTrade || isCrossAccountTradeSupported(SwapperName.ArbitrumBridge)), [SwapperName.Portals]: - Portals && (!isCrossAccountTrade || isCrossAccountTradeSupported(SwapperName.Portals)), + PortalsSwap && (!isCrossAccountTrade || isCrossAccountTradeSupported(SwapperName.Portals)), [SwapperName.Chainflip]: - Chainflip && (!isCrossAccountTrade || isCrossAccountTradeSupported(SwapperName.Chainflip)), + ChainflipSwap && + (!isCrossAccountTrade || isCrossAccountTradeSupported(SwapperName.Chainflip)), [SwapperName.Jupiter]: - Jupiter && (!isCrossAccountTrade || isCrossAccountTradeSupported(SwapperName.Jupiter)), + JupiterSwap && (!isCrossAccountTrade || isCrossAccountTradeSupported(SwapperName.Jupiter)), [SwapperName.Test]: false, } } diff --git a/src/state/slices/preferencesSlice/preferencesSlice.ts b/src/state/slices/preferencesSlice/preferencesSlice.ts index 8e500ef2a38..faeb29a90b7 100644 --- a/src/state/slices/preferencesSlice/preferencesSlice.ts +++ b/src/state/slices/preferencesSlice/preferencesSlice.ts @@ -37,7 +37,7 @@ export type FeatureFlags = { ReadOnlyAssets: boolean Jaypegz: boolean ArbitrumBridge: boolean - Portals: boolean + PortalsSwap: boolean CovalentJaypegs: boolean Chatwoot: boolean AdvancedSlippage: boolean @@ -68,11 +68,11 @@ export type FeatureFlags = { FoxPageFoxFarmingSection: boolean FoxPageGovernance: boolean LimitOrders: boolean - Chainflip: boolean + ChainflipSwap: boolean ChainflipDca: boolean PublicTradeRoute: boolean ThorFreeFees: boolean - Jupiter: boolean + JupiterSwap: boolean } export type Flag = keyof FeatureFlags @@ -134,7 +134,7 @@ const initialState: Preferences = { DynamicLpAssets: getConfig().REACT_APP_FEATURE_DYNAMIC_LP_ASSETS, ReadOnlyAssets: getConfig().REACT_APP_FEATURE_READ_ONLY_ASSETS, ArbitrumBridge: getConfig().REACT_APP_FEATURE_ARBITRUM_BRIDGE, - Portals: getConfig().REACT_APP_FEATURE_PORTALS_SWAPPER, + PortalsSwap: getConfig().REACT_APP_FEATURE_PORTALS_SWAPPER, Chatwoot: getConfig().REACT_APP_FEATURE_CHATWOOT, AdvancedSlippage: getConfig().REACT_APP_FEATURE_ADVANCED_SLIPPAGE, WalletConnectV2: getConfig().REACT_APP_FEATURE_WALLET_CONNECT_V2, @@ -164,11 +164,11 @@ const initialState: Preferences = { FoxPageFoxFarmingSection: getConfig().REACT_APP_FEATURE_FOX_PAGE_FOX_FARMING_SECTION, FoxPageGovernance: getConfig().REACT_APP_FEATURE_FOX_PAGE_GOVERNANCE, LimitOrders: getConfig().REACT_APP_FEATURE_LIMIT_ORDERS, - Chainflip: getConfig().REACT_APP_FEATURE_CHAINFLIP, - ChainflipDca: getConfig().REACT_APP_FEATURE_CHAINFLIP_DCA, + ChainflipSwap: getConfig().REACT_APP_FEATURE_CHAINFLIP_SWAP, + ChainflipDca: getConfig().REACT_APP_FEATURE_CHAINFLIP_SWAP_DCA, PublicTradeRoute: getConfig().REACT_APP_FEATURE_PUBLIC_TRADE_ROUTE, ThorFreeFees: getConfig().REACT_APP_FEATURE_THOR_FREE_FEES, - Jupiter: getConfig().REACT_APP_FEATURE_JUPITER, + JupiterSwap: getConfig().REACT_APP_FEATURE_JUPITER_SWAP, }, selectedLocale: simpleLocale(), balanceThreshold: '0', diff --git a/src/test/mocks/store.ts b/src/test/mocks/store.ts index 96a72e8c26b..3ee960a87b0 100644 --- a/src/test/mocks/store.ts +++ b/src/test/mocks/store.ts @@ -120,7 +120,7 @@ export const mockStore: ReduxState = { ArbitrumBridgeClaims: false, UsdtApprovalReset: false, RunePool: false, - Portals: false, + PortalsSwap: false, Markets: false, PhantomWallet: false, FoxPage: false, @@ -129,11 +129,11 @@ export const mockStore: ReduxState = { FoxPageFoxFarmingSection: false, FoxPageGovernance: false, LimitOrders: false, - Chainflip: false, + ChainflipSwap: false, ChainflipDca: false, PublicTradeRoute: false, ThorFreeFees: false, - Jupiter: false, + JupiterSwap: false, }, selectedLocale: 'en', balanceThreshold: '0', From 4e76e8115223d91bd602f7d9ceed80c94c77ea15 Mon Sep 17 00:00:00 2001 From: NeOMakinG <14963751+NeOMakinG@users.noreply.github.com> Date: Mon, 25 Nov 2024 12:42:26 +0100 Subject: [PATCH 117/127] fix: review feedbacks --- .env.base | 2 +- .env.dev | 2 +- .env.develop | 2 +- .../src/solana/SolanaChainAdapter.ts | 72 ++++++++++--------- packages/chain-adapters/src/utils/index.ts | 1 - packages/chain-adapters/src/utils/svmUtils.ts | 9 --- .../getCowSwapTradeQuote.test.ts | 6 -- .../swappers/JupiterSwapper/JupiterSwapper.ts | 3 +- .../src/swappers/JupiterSwapper/endpoints.ts | 16 ++--- .../swapperApi/getTradeQuote.ts | 10 ++- .../JupiterSwapper/utils/constants.ts | 2 +- .../swappers/JupiterSwapper/utils/helpers.ts | 9 +-- .../JupiterSwapper/utils/jupiterService.ts | 2 +- .../filterBuyAssetsBySellAssetId.ts | 23 +----- .../utils/test-data/setupSwapQuote.ts | 1 - packages/swapper/src/types.ts | 12 +--- packages/swapper/src/utils.ts | 5 +- packages/types/src/base.ts | 2 - .../useGetTradeQuotes/getTradeQuoteInput.ts | 6 +- .../useGetTradeQuotes/useGetTradeQuotes.tsx | 2 +- .../useGetTradeQuotes/useGetTradeRates.tsx | 2 +- src/components/MultiHopTrade/types.ts | 2 +- .../Stake/Bridge/hooks/useRfoxBridge.ts | 1 - 23 files changed, 71 insertions(+), 121 deletions(-) delete mode 100644 packages/chain-adapters/src/utils/svmUtils.ts diff --git a/.env.base b/.env.base index 91cc8884698..da09f338505 100644 --- a/.env.base +++ b/.env.base @@ -62,7 +62,7 @@ REACT_APP_FEATURE_READ_ONLY_ASSETS=true # swapper feature flags - other .env files will override these REACT_APP_FEATURE_CHAINFLIP_SWAP=false -REACT_APP_FEATURE_CHAINFLIP_DCA=false +REACT_APP_FEATURE_CHAINFLIP_SWAP_DCA=false REACT_APP_FEATURE_COWSWAP=true REACT_APP_FEATURE_LIFI_SWAP=true REACT_APP_FEATURE_THOR_SWAP=true diff --git a/.env.dev b/.env.dev index 5021c9462ce..316ae4e9e0c 100644 --- a/.env.dev +++ b/.env.dev @@ -1,6 +1,6 @@ # feature flags REACT_APP_FEATURE_CHAINFLIP_SWAP=true -REACT_APP_FEATURE_CHAINFLIP_DCA=false +REACT_APP_FEATURE_CHAINFLIP_SWAP_DCA=false REACT_APP_FEATURE_PUBLIC_TRADE_ROUTE=false REACT_APP_FEATURE_LIMIT_ORDERS=true REACT_APP_FEATURE_JUPITER_SWAP=true diff --git a/.env.develop b/.env.develop index 511edd77407..7b29e24fb96 100644 --- a/.env.develop +++ b/.env.develop @@ -2,7 +2,7 @@ REACT_APP_FEATURE_LIMIT_ORDERS=true REACT_APP_FEATURE_PUBLIC_TRADE_ROUTE=false REACT_APP_FEATURE_CHAINFLIP_SWAP=true -REACT_APP_FEATURE_CHAINFLIP_DCA=false +REACT_APP_FEATURE_CHAINFLIP_SWAP_DCA=false # mixpanel REACT_APP_MIXPANEL_TOKEN=1c1369f6ea23a6404bac41b42817cc4b diff --git a/packages/chain-adapters/src/solana/SolanaChainAdapter.ts b/packages/chain-adapters/src/solana/SolanaChainAdapter.ts index eb9eadff925..0db0ce6981c 100644 --- a/packages/chain-adapters/src/solana/SolanaChainAdapter.ts +++ b/packages/chain-adapters/src/solana/SolanaChainAdapter.ts @@ -38,6 +38,7 @@ import { TransactionMessage, VersionedTransaction, } from '@solana/web3.js' +import { isUndefined } from 'lodash' import PQueue from 'p-queue' import type { ChainAdapter as IChainAdapter } from '../api' @@ -466,6 +467,7 @@ export class ChainAdapter implements IChainAdapter chainSpecific.addressLookupTableAccounts ?? [], ) + if (isUndefined(input.to)) throw new Error(`${this.getName()}ChainAdapter: value is required`) if (!input.value) throw new Error(`${this.getName()}ChainAdapter: value is required`) const value = Number(input.value) @@ -512,6 +514,38 @@ export class ChainAdapter implements IChainAdapter return Buffer.from(transaction.serialize()).toString('base64') } + private async buildTokenTransferInstructions({ + from, + to, + tokenId, + value, + }: { + from: string + to: string + tokenId: string + value: string + }): Promise { + const instructions: TransactionInstruction[] = [] + + const { instruction, destinationTokenAccount } = + await this.createAssociatedTokenAccountInstruction({ from, to, tokenId }) + + if (instruction) { + instructions.push(instruction) + } + + instructions.push( + createTransferInstruction( + getAssociatedTokenAddressSync(new PublicKey(tokenId), new PublicKey(from), true), + destinationTokenAccount, + new PublicKey(from), + Number(value), + ), + ) + + return instructions + } + public async createAssociatedTokenAccountInstruction({ from, to, @@ -566,38 +600,6 @@ export class ChainAdapter implements IChainAdapter } } - private async buildTokenTransferInstructions({ - from, - to, - tokenId, - value, - }: { - from: string - to: string - tokenId: string - value: string - }): Promise { - const instructions: TransactionInstruction[] = [] - - const { instruction, destinationTokenAccount } = - await this.createAssociatedTokenAccountInstruction({ from, to, tokenId }) - - if (instruction) { - instructions.push(instruction) - } - - instructions.push( - createTransferInstruction( - getAssociatedTokenAddressSync(new PublicKey(tokenId), new PublicKey(from), true), - destinationTokenAccount, - new PublicKey(from), - Number(value), - ), - ) - - return instructions - } - public convertInstruction(instruction: TransactionInstruction): SolanaTxInstruction { return { keys: instruction.keys.map(key => ({ @@ -636,13 +638,13 @@ export class ChainAdapter implements IChainAdapter return this.providers.http } - public async getAddressLookupTableAccountsInfo( + private async getAddressLookupTableAccountsInfo( addresses: string[], ): Promise<(AccountInfo | null)[]> { return await this.connection.getMultipleAccountsInfo(addresses.map(key => new PublicKey(key))) } - public async getSolanaAddressLookupTableAccountsInfo( + private async getSolanaAddressLookupTableAccountsInfo( addresses: string[], ): Promise { const addressLookupTableAccountInfos = await this.getAddressLookupTableAccountsInfo(addresses) @@ -663,7 +665,7 @@ export class ChainAdapter implements IChainAdapter }, new Array()) } - public async getAddressLookupTableAccounts( + private async getAddressLookupTableAccounts( addresses: string[], ): Promise { const addressLookupTableAccountInfos = await this.getAddressLookupTableAccountsInfo(addresses) diff --git a/packages/chain-adapters/src/utils/index.ts b/packages/chain-adapters/src/utils/index.ts index 4537818a8df..cacfec3cd12 100644 --- a/packages/chain-adapters/src/utils/index.ts +++ b/packages/chain-adapters/src/utils/index.ts @@ -5,7 +5,6 @@ export * from './bignumber' export * from './bip44' export * from './fees' export * from './utxoUtils' -export * from './svmUtils' export * from './ledgerAppGate' export const getAssetNamespace = (type: string): AssetNamespace => { diff --git a/packages/chain-adapters/src/utils/svmUtils.ts b/packages/chain-adapters/src/utils/svmUtils.ts deleted file mode 100644 index e525a2be3b0..00000000000 --- a/packages/chain-adapters/src/utils/svmUtils.ts +++ /dev/null @@ -1,9 +0,0 @@ -import type { SvmChainId } from '@shapeshiftoss/types' - -import { svmChainIds } from '../solana/SolanaChainAdapter' - -export const isSvmChainId = ( - maybeSvmChainId: string | SvmChainId, -): maybeSvmChainId is SvmChainId => { - return svmChainIds.includes(maybeSvmChainId as SvmChainId) -} diff --git a/packages/swapper/src/swappers/CowSwapper/getCowSwapTradeQuote/getCowSwapTradeQuote.test.ts b/packages/swapper/src/swappers/CowSwapper/getCowSwapTradeQuote/getCowSwapTradeQuote.test.ts index 0768c5c2802..8e4dc7ef4d6 100644 --- a/packages/swapper/src/swappers/CowSwapper/getCowSwapTradeQuote/getCowSwapTradeQuote.test.ts +++ b/packages/swapper/src/swappers/CowSwapper/getCowSwapTradeQuote/getCowSwapTradeQuote.test.ts @@ -372,7 +372,6 @@ describe('getCowSwapTradeQuote', () => { sellAmountIncludingProtocolFeesCryptoBaseUnit: '11111', accountNumber: 0, receiveAddress: DEFAULT_ADDRESS, - isManualReceiveAddress: false, affiliateBps: '0', potentialAffiliateBps: '0', supportsEIP1559: false, @@ -400,7 +399,6 @@ describe('getCowSwapTradeQuote', () => { sellAmountIncludingProtocolFeesCryptoBaseUnit: '1000000000000000000', accountNumber: 0, receiveAddress: DEFAULT_ADDRESS, - isManualReceiveAddress: false, affiliateBps: '0', potentialAffiliateBps: '0', supportsEIP1559: false, @@ -446,7 +444,6 @@ describe('getCowSwapTradeQuote', () => { sellAmountIncludingProtocolFeesCryptoBaseUnit: '1000000000000000000000', accountNumber: 0, receiveAddress: DEFAULT_ADDRESS, - isManualReceiveAddress: false, affiliateBps: '0', potentialAffiliateBps: '0', supportsEIP1559: false, @@ -492,7 +489,6 @@ describe('getCowSwapTradeQuote', () => { sellAmountIncludingProtocolFeesCryptoBaseUnit: '20000000', accountNumber: 0, receiveAddress: DEFAULT_ADDRESS, - isManualReceiveAddress: false, affiliateBps: '0', potentialAffiliateBps: '0', supportsEIP1559: false, @@ -538,7 +534,6 @@ describe('getCowSwapTradeQuote', () => { sellAmountIncludingProtocolFeesCryptoBaseUnit: '500000', accountNumber: 0, receiveAddress: DEFAULT_ADDRESS, - isManualReceiveAddress: false, affiliateBps: '0', potentialAffiliateBps: '0', supportsEIP1559: false, @@ -584,7 +579,6 @@ describe('getCowSwapTradeQuote', () => { sellAmountIncludingProtocolFeesCryptoBaseUnit: '1000000000000', accountNumber: 0, receiveAddress: DEFAULT_ADDRESS, - isManualReceiveAddress: false, affiliateBps: '0', potentialAffiliateBps: '0', supportsEIP1559: false, diff --git a/packages/swapper/src/swappers/JupiterSwapper/JupiterSwapper.ts b/packages/swapper/src/swappers/JupiterSwapper/JupiterSwapper.ts index 12c4b2c8845..eb1966aead0 100644 --- a/packages/swapper/src/swappers/JupiterSwapper/JupiterSwapper.ts +++ b/packages/swapper/src/swappers/JupiterSwapper/JupiterSwapper.ts @@ -3,7 +3,6 @@ import type { Asset } from '@shapeshiftoss/types' import { executeSolanaTransaction } from '../..' import type { BuyAssetBySellIdInput, Swapper } from '../../types' -import { filterSameChainSolanaBuyAssetsBySellAssetId } from '../utils/filterBuyAssetsBySellAssetId/filterBuyAssetsBySellAssetId' import { jupiterSupportedChainIds } from './utils/constants' export const jupiterSwapper: Swapper = { @@ -22,7 +21,7 @@ export const jupiterSwapper: Swapper = { filterBuyAssetsBySellAssetId: (input: BuyAssetBySellIdInput): Promise => { return Promise.resolve( - filterSameChainSolanaBuyAssetsBySellAssetId(input) + input.assets .filter(asset => { const { chainId } = asset return jupiterSupportedChainIds.includes(chainId) diff --git a/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts b/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts index 1b5e541584d..2b4cf925818 100644 --- a/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts +++ b/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts @@ -1,4 +1,4 @@ -import { CHAIN_NAMESPACE, fromAssetId, solAssetId } from '@shapeshiftoss/caip' +import { CHAIN_NAMESPACE, fromAssetId, solAssetId, wrappedSolAssetId } from '@shapeshiftoss/caip' import type { BuildSendApiTxInput, GetFeeDataInput } from '@shapeshiftoss/chain-adapters' import type { SolanaSignTx } from '@shapeshiftoss/hdwallet-core' import type { KnownChainIds } from '@shapeshiftoss/types' @@ -38,14 +38,14 @@ export const jupiterApi: SwapperApi = { const adapter = assertGetSolanaChainAdapter(step.sellAsset.chainId) - const isManualReceiveAddress = tradeQuote.receiveAddress !== from + const isCrossAccountTrade = tradeQuote.receiveAddress !== from - if (isManualReceiveAddress && step.buyAsset.assetId === solAssetId) { + if (isCrossAccountTrade && step.buyAsset.assetId === solAssetId) { throw Error('Manual receive address is not supported for SOL') } const { instruction: createTokenAccountInstruction, destinationTokenAccount } = - contractAddress && isManualReceiveAddress + contractAddress && isCrossAccountTrade ? await adapter.createAssociatedTokenAccountInstruction({ from, to: tradeQuote.receiveAddress, @@ -56,11 +56,12 @@ export const jupiterApi: SwapperApi = { const maybeSwapResponse = await getJupiterSwapInstructions({ apiUrl: jupiterUrl, fromAddress: from, - toAddress: isManualReceiveAddress ? destinationTokenAccount?.toString() : undefined, + toAddress: isCrossAccountTrade ? destinationTokenAccount?.toString() : undefined, rawQuote: tradeQuote.rawQuote, + wrapAndUnwrapSol: step.buyAsset.assetId === wrappedSolAssetId ? false : true, // Shared account is not supported for simple AMMs useSharedAccounts: - tradeQuote.rawQuote.routePlan.length > 1 && isManualReceiveAddress ? true : false, + tradeQuote.rawQuote.routePlan.length > 1 && isCrossAccountTrade ? true : false, }) if (maybeSwapResponse.isErr()) { @@ -101,8 +102,7 @@ export const jupiterApi: SwapperApi = { case CHAIN_NAMESPACE.Solana: { const sellAdapter = assertGetSolanaChainAdapter(step.sellAsset.chainId) const getFeeDataInput: GetFeeDataInput = { - // Simulates a self-send - to: from, + to: '', value: '0', chainSpecific: { from, diff --git a/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeQuote.ts b/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeQuote.ts index dcbccb8d6f9..b5e9800b0bf 100644 --- a/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeQuote.ts +++ b/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeQuote.ts @@ -41,14 +41,14 @@ const _getTradeQuote = async ( receiveAddress, accountNumber, slippageTolerancePercentageDecimal, - isManualReceiveAddress, + isCrossAccountTrade, } = input const { assetsById } = deps const jupiterUrl = deps.config.REACT_APP_JUPITER_API_URL - if (isManualReceiveAddress && buyAsset.assetId === solAssetId) { + if (isCrossAccountTrade && buyAsset.assetId === solAssetId) { return Err( makeSwapErrorRight({ message: `unsupported manual receive address for SOL`, @@ -107,8 +107,7 @@ const _getTradeQuote = async ( case CHAIN_NAMESPACE.Solana: { const sellAdapter = deps.assertGetSolanaChainAdapter(sellAsset.chainId) const getFeeDataInput: GetFeeDataInput = { - // Simulates a self-send, since we don't know the to just yet at this stage - to: input.sendAddress!, + to: receiveAddress ?? input.sendAddress, value: sellAmount, chainSpecific: { from: input.sendAddress!, @@ -143,7 +142,7 @@ const _getTradeQuote = async ( acc[feeAssetId] = { requiresBalance: false, - amountCryptoBaseUnit: bnOrZero(route.swapInfo.feeAmount).toString(), + amountCryptoBaseUnit: bnOrZero(route.swapInfo.feeAmount).toFixed(0), asset: feeAsset, } @@ -173,7 +172,6 @@ const _getTradeQuote = async ( receiveAddress, potentialAffiliateBps: affiliateBps, affiliateBps, - isStreaming: false, rawQuote: quoteResponse, slippageTolerancePercentageDecimal: slippageTolerancePercentageDecimal ?? diff --git a/packages/swapper/src/swappers/JupiterSwapper/utils/constants.ts b/packages/swapper/src/swappers/JupiterSwapper/utils/constants.ts index f9c97ecbfd9..37b3987a56d 100644 --- a/packages/swapper/src/swappers/JupiterSwapper/utils/constants.ts +++ b/packages/swapper/src/swappers/JupiterSwapper/utils/constants.ts @@ -3,7 +3,7 @@ import { KnownChainIds } from '@shapeshiftoss/types' import type { SupportedChainIds } from '../../../types' -export const jupiterSupportedChainIds = [KnownChainIds.SolanaMainnet] as ChainId[] +export const jupiterSupportedChainIds: ChainId[] = [KnownChainIds.SolanaMainnet] export const JUPITER_SUPPORTED_CHAIN_IDS: SupportedChainIds = { sell: jupiterSupportedChainIds, diff --git a/packages/swapper/src/swappers/JupiterSwapper/utils/helpers.ts b/packages/swapper/src/swappers/JupiterSwapper/utils/helpers.ts index 1ba0fcce6e3..272c93d244b 100644 --- a/packages/swapper/src/swappers/JupiterSwapper/utils/helpers.ts +++ b/packages/swapper/src/swappers/JupiterSwapper/utils/helpers.ts @@ -1,4 +1,5 @@ import { type ChainId, fromAssetId } from '@shapeshiftoss/caip' +import type { KnownChainIds } from '@shapeshiftoss/types' import type { Result } from '@sniptt/monads' import type { AxiosResponse } from 'axios' @@ -8,7 +9,7 @@ import type { SwapInstructionsResponse } from '../models/SwapInstructionsRespons import { jupiterSupportedChainIds } from './constants' import { jupiterService } from './jupiterService' -export const isSupportedChainId = (chainId: ChainId): chainId is ChainId => { +export const isSupportedChainId = (chainId: ChainId): chainId is KnownChainIds.SolanaMainnet => { return jupiterSupportedChainIds.includes(chainId) } @@ -20,7 +21,7 @@ type GetJupiterQuoteArgs = { destinationAsset: string commissionBps: string amount: string - slippageBps?: string + slippageBps: string } type GetJupiterSwapArgs = { @@ -29,7 +30,7 @@ type GetJupiterSwapArgs = { rawQuote: unknown toAddress?: string useSharedAccounts: boolean - wrapAndUnwrapSol?: boolean + wrapAndUnwrapSol: boolean } export const getJupiterQuote = ({ @@ -57,7 +58,7 @@ export const getJupiterSwapInstructions = ({ toAddress, rawQuote, useSharedAccounts, - wrapAndUnwrapSol = true, + wrapAndUnwrapSol, }: GetJupiterSwapArgs): Promise< Result, SwapErrorRight> > => diff --git a/packages/swapper/src/swappers/JupiterSwapper/utils/jupiterService.ts b/packages/swapper/src/swappers/JupiterSwapper/utils/jupiterService.ts index 206f0968015..2657249d8a6 100644 --- a/packages/swapper/src/swappers/JupiterSwapper/utils/jupiterService.ts +++ b/packages/swapper/src/swappers/JupiterSwapper/utils/jupiterService.ts @@ -1,7 +1,7 @@ import { SwapperName } from '../../../types' import { createCache, makeSwapperAxiosServiceMonadic } from '../../../utils' -const maxAgeMillis = 15 * 1000 // 15 seconds ttl for all except cached to get fresh status updates +const maxAgeMillis = 15 * 1000 const cachedUrls: string[] = [] const axiosConfig = { diff --git a/packages/swapper/src/swappers/utils/filterBuyAssetsBySellAssetId/filterBuyAssetsBySellAssetId.ts b/packages/swapper/src/swappers/utils/filterBuyAssetsBySellAssetId/filterBuyAssetsBySellAssetId.ts index c9689a29659..816dc33954a 100644 --- a/packages/swapper/src/swappers/utils/filterBuyAssetsBySellAssetId/filterBuyAssetsBySellAssetId.ts +++ b/packages/swapper/src/swappers/utils/filterBuyAssetsBySellAssetId/filterBuyAssetsBySellAssetId.ts @@ -1,5 +1,5 @@ import { arbitrumNovaChainId, type ChainId } from '@shapeshiftoss/caip' -import { isEvmChainId, isSvmChainId } from '@shapeshiftoss/chain-adapters' +import { isEvmChainId } from '@shapeshiftoss/chain-adapters' import type { Asset } from '@shapeshiftoss/types' import type { BuyAssetBySellIdInput } from '../../../types' @@ -23,19 +23,6 @@ const _filterEvmBuyAssetsBySellAssetId = ( }) } -const _filterSolanaBuyAssetsBySellAssetId = ( - { assets, sellAsset }: BuyAssetBySellIdInput, - chainIdPredicate: ChainIdPredicate, -): Asset[] => { - // evm only - if (!isSvmChainId(sellAsset.chainId)) return [] - - return assets.filter(buyAsset => { - // evm only AND chain id predicate with no arbitrum nova support for any swappers - return isSvmChainId(buyAsset.chainId) && chainIdPredicate(buyAsset.chainId, sellAsset.chainId) - }) -} - export const filterSameChainEvmBuyAssetsBySellAssetId = (input: BuyAssetBySellIdInput): Asset[] => { const sameChainIdPredicate = (buyAssetChainId: ChainId, sellAssetChainId: ChainId): boolean => buyAssetChainId === sellAssetChainId @@ -49,11 +36,3 @@ export const filterCrossChainEvmBuyAssetsBySellAssetId = ( buyAssetChainId !== sellAssetChainId return _filterEvmBuyAssetsBySellAssetId(input, crossChainIdPredicate) } - -export const filterSameChainSolanaBuyAssetsBySellAssetId = ( - input: BuyAssetBySellIdInput, -): Asset[] => { - const sameChainIdPredicate = (buyAssetChainId: ChainId, sellAssetChainId: ChainId): boolean => - buyAssetChainId === sellAssetChainId - return _filterSolanaBuyAssetsBySellAssetId(input, sameChainIdPredicate) -} diff --git a/packages/swapper/src/swappers/utils/test-data/setupSwapQuote.ts b/packages/swapper/src/swappers/utils/test-data/setupSwapQuote.ts index 141a941b6fb..72deb5d7a15 100644 --- a/packages/swapper/src/swappers/utils/test-data/setupSwapQuote.ts +++ b/packages/swapper/src/swappers/utils/test-data/setupSwapQuote.ts @@ -43,7 +43,6 @@ export const setupQuote = () => { buyAsset, accountNumber: 0, receiveAddress: '0xc770eefad204b5180df6a14ee197d99d808ee52d', - isManualReceiveAddress: false, affiliateBps: '0', potentialAffiliateBps: '0', supportsEIP1559: false, diff --git a/packages/swapper/src/types.ts b/packages/swapper/src/types.ts index e926cd99e6f..39262a1d389 100644 --- a/packages/swapper/src/types.ts +++ b/packages/swapper/src/types.ts @@ -147,7 +147,7 @@ type CommonTradeInputBase = { export type CommonTradeQuoteInput = CommonTradeInputBase & { sendAddress?: string receiveAddress: string - isManualReceiveAddress: boolean + isCrossAccountTrade?: boolean accountNumber: number quoteOrRate: 'quote' } @@ -155,7 +155,7 @@ export type CommonTradeQuoteInput = CommonTradeInputBase & { type CommonTradeRateInput = CommonTradeInputBase & { sendAddress?: undefined receiveAddress: undefined - isManualReceiveAddress: boolean + isCrossAccountTrade?: boolean accountNumber: undefined quoteOrRate: 'rate' } @@ -435,14 +435,6 @@ export type CheckTradeStatusInput = { type TradeQuoteResult = Result export type TradeRateResult = Result -export type SolanaTransactionRequest = { - gasLimit: string - to: string - from: string - value: string - data: string -} - export type EvmTransactionRequest = { gasLimit: string to: string diff --git a/packages/swapper/src/utils.ts b/packages/swapper/src/utils.ts index a230fc30aa3..99b2b8248be 100644 --- a/packages/swapper/src/utils.ts +++ b/packages/swapper/src/utils.ts @@ -4,6 +4,7 @@ import { type ChainId, fromAccountId, fromAssetId, + solanaChainId, } from '@shapeshiftoss/caip' import type { EvmChainAdapter } from '@shapeshiftoss/chain-adapters' import type { ChainAdapter as SolanaChainAdapter } from '@shapeshiftoss/chain-adapters/dist/solana/SolanaChainAdapter' @@ -328,13 +329,11 @@ export const isExecutableTradeStep = (step: TradeQuoteStep): step is ExecutableT export const checkSolanaSwapStatus = async ({ txHash, - chainId, accountId, assertGetSolanaChainAdapter, }: { txHash: string accountId: AccountId | undefined - chainId: ChainId assertGetSolanaChainAdapter: (chainId: ChainId) => SolanaChainAdapter }): Promise<{ status: TxStatus @@ -345,7 +344,7 @@ export const checkSolanaSwapStatus = async ({ if (!accountId) throw new Error('Missing accountId') const account = fromAccountId(accountId).account - const adapter = assertGetSolanaChainAdapter(chainId) + const adapter = assertGetSolanaChainAdapter(solanaChainId) const tx = await adapter.httpProvider.getTransaction({ txid: txHash }) const status = await adapter.getTxStatus(tx, account) diff --git a/packages/types/src/base.ts b/packages/types/src/base.ts index b872606f016..36994e9c872 100644 --- a/packages/types/src/base.ts +++ b/packages/types/src/base.ts @@ -48,8 +48,6 @@ export type UtxoChainId = | KnownChainIds.DogecoinMainnet | KnownChainIds.LitecoinMainnet -export type SvmChainId = KnownChainIds.SolanaMainnet - export enum WithdrawType { DELAYED, INSTANT, diff --git a/src/components/MultiHopTrade/hooks/useGetTradeQuotes/getTradeQuoteInput.ts b/src/components/MultiHopTrade/hooks/useGetTradeQuotes/getTradeQuoteInput.ts index cb15e7a3dad..6baa68423fc 100644 --- a/src/components/MultiHopTrade/hooks/useGetTradeQuotes/getTradeQuoteInput.ts +++ b/src/components/MultiHopTrade/hooks/useGetTradeQuotes/getTradeQuoteInput.ts @@ -28,7 +28,7 @@ export type GetTradeQuoteInputArgs = { pubKey?: string | undefined quoteOrRate: 'quote' | 'rate' receiveAddress: string | undefined - isManualReceiveAddress: boolean + isCrossAccountTrade?: boolean sellAccountNumber: number | undefined wallet: HDWallet | undefined } @@ -47,7 +47,7 @@ export const getTradeQuoteInput = async ({ potentialAffiliateBps, slippageTolerancePercentageDecimal, pubKey, - isManualReceiveAddress, + isCrossAccountTrade, }: GetTradeQuoteInputArgs): Promise => { const tradeQuoteInputCommonArgs: TradeQuoteInputCommonArgs = { sellAmountIncludingProtocolFeesCryptoBaseUnit: toBaseUnit( @@ -57,7 +57,7 @@ export const getTradeQuoteInput = async ({ sellAsset, buyAsset, receiveAddress, - isManualReceiveAddress, + isCrossAccountTrade, accountNumber: sellAccountNumber, affiliateBps: affiliateBps ?? '0', potentialAffiliateBps: potentialAffiliateBps ?? '0', diff --git a/src/components/MultiHopTrade/hooks/useGetTradeQuotes/useGetTradeQuotes.tsx b/src/components/MultiHopTrade/hooks/useGetTradeQuotes/useGetTradeQuotes.tsx index e7cd5181d33..f293e13d1f6 100644 --- a/src/components/MultiHopTrade/hooks/useGetTradeQuotes/useGetTradeQuotes.tsx +++ b/src/components/MultiHopTrade/hooks/useGetTradeQuotes/useGetTradeQuotes.tsx @@ -276,7 +276,7 @@ export const useGetTradeQuotes = () => { wallet: wallet ?? undefined, quoteOrRate: 'quote', receiveAddress, - isManualReceiveAddress: Boolean(manualReceiveAddress), + isCrossAccountTrade: Boolean(manualReceiveAddress), sellAmountBeforeFeesCryptoPrecision: sellAmountCryptoPrecision, allowMultiHop: true, affiliateBps, diff --git a/src/components/MultiHopTrade/hooks/useGetTradeQuotes/useGetTradeRates.tsx b/src/components/MultiHopTrade/hooks/useGetTradeQuotes/useGetTradeRates.tsx index fd782715f8d..778e17e367b 100644 --- a/src/components/MultiHopTrade/hooks/useGetTradeQuotes/useGetTradeRates.tsx +++ b/src/components/MultiHopTrade/hooks/useGetTradeQuotes/useGetTradeRates.tsx @@ -224,7 +224,7 @@ export const useGetTradeRates = () => { allowMultiHop: true, affiliateBps, potentialAffiliateBps, - isManualReceiveAddress: Boolean(manualReceiveAddress), + isCrossAccountTrade: Boolean(manualReceiveAddress), // Pass in the user's slippage preference if it's set, else let the swapper use its default slippageTolerancePercentageDecimal: userSlippageTolerancePercentageDecimal, pubKey: diff --git a/src/components/MultiHopTrade/types.ts b/src/components/MultiHopTrade/types.ts index 970e6c22ff0..c59d228664a 100644 --- a/src/components/MultiHopTrade/types.ts +++ b/src/components/MultiHopTrade/types.ts @@ -26,7 +26,7 @@ export type TradeQuoteInputCommonArgs = Pick< | 'sellAsset' | 'buyAsset' | 'receiveAddress' - | 'isManualReceiveAddress' + | 'isCrossAccountTrade' | 'accountNumber' | 'affiliateBps' | 'potentialAffiliateBps' diff --git a/src/pages/RFOX/components/Stake/Bridge/hooks/useRfoxBridge.ts b/src/pages/RFOX/components/Stake/Bridge/hooks/useRfoxBridge.ts index 01afed7cbaf..19e25b07f04 100644 --- a/src/pages/RFOX/components/Stake/Bridge/hooks/useRfoxBridge.ts +++ b/src/pages/RFOX/components/Stake/Bridge/hooks/useRfoxBridge.ts @@ -141,7 +141,6 @@ export const useRfoxBridge = ({ confirmedQuote }: UseRfoxBridgeProps): UseRfoxBr potentialAffiliateBps: '0', allowMultiHop: true, receiveAddress: fromAccountId(confirmedQuote.buyAssetAccountId).account, - isManualReceiveAddress: false, sendAddress: fromAccountId(confirmedQuote.sellAssetAccountId).account, accountNumber: sellAssetAccountNumber, hasWallet: Boolean(walletInfo?.deviceId), From 0001e5316ccd4395724ab75e36a101390df9b1d8 Mon Sep 17 00:00:00 2001 From: NeOMakinG <14963751+NeOMakinG@users.noreply.github.com> Date: Tue, 26 Nov 2024 01:05:38 +0100 Subject: [PATCH 118/127] fix: review feedbacks --- .../chain-adapters/src/solana/SolanaChainAdapter.ts | 2 +- .../JupiterSwapper/swapperApi/getTradeQuote.ts | 10 ---------- packages/swapper/src/types.ts | 2 -- .../hooks/useGetTradeQuotes/getTradeQuoteInput.ts | 3 --- .../hooks/useGetTradeQuotes/useGetTradeQuotes.tsx | 2 -- .../hooks/useGetTradeQuotes/useGetTradeRates.tsx | 2 -- src/components/MultiHopTrade/types.ts | 1 - src/state/apis/swapper/swapperApi.ts | 11 ++++++++--- src/state/helpers.ts | 5 ++++- src/state/slices/tradeQuoteSlice/selectors.ts | 2 +- 10 files changed, 14 insertions(+), 26 deletions(-) diff --git a/packages/chain-adapters/src/solana/SolanaChainAdapter.ts b/packages/chain-adapters/src/solana/SolanaChainAdapter.ts index 0db0ce6981c..a2cc85d81af 100644 --- a/packages/chain-adapters/src/solana/SolanaChainAdapter.ts +++ b/packages/chain-adapters/src/solana/SolanaChainAdapter.ts @@ -467,7 +467,7 @@ export class ChainAdapter implements IChainAdapter chainSpecific.addressLookupTableAccounts ?? [], ) - if (isUndefined(input.to)) throw new Error(`${this.getName()}ChainAdapter: value is required`) + if (isUndefined(input.to)) throw new Error(`${this.getName()}ChainAdapter: to is required`) if (!input.value) throw new Error(`${this.getName()}ChainAdapter: value is required`) const value = Number(input.value) diff --git a/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeQuote.ts b/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeQuote.ts index b5e9800b0bf..e2e4eefa5f7 100644 --- a/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeQuote.ts +++ b/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeQuote.ts @@ -41,22 +41,12 @@ const _getTradeQuote = async ( receiveAddress, accountNumber, slippageTolerancePercentageDecimal, - isCrossAccountTrade, } = input const { assetsById } = deps const jupiterUrl = deps.config.REACT_APP_JUPITER_API_URL - if (isCrossAccountTrade && buyAsset.assetId === solAssetId) { - return Err( - makeSwapErrorRight({ - message: `unsupported manual receive address for SOL`, - code: TradeQuoteError.UnsupportedTradePair, - }), - ) - } - if (!isSupportedChainId(sellAsset.chainId)) { return Err( makeSwapErrorRight({ diff --git a/packages/swapper/src/types.ts b/packages/swapper/src/types.ts index 39262a1d389..46f36c8ff81 100644 --- a/packages/swapper/src/types.ts +++ b/packages/swapper/src/types.ts @@ -147,7 +147,6 @@ type CommonTradeInputBase = { export type CommonTradeQuoteInput = CommonTradeInputBase & { sendAddress?: string receiveAddress: string - isCrossAccountTrade?: boolean accountNumber: number quoteOrRate: 'quote' } @@ -155,7 +154,6 @@ export type CommonTradeQuoteInput = CommonTradeInputBase & { type CommonTradeRateInput = CommonTradeInputBase & { sendAddress?: undefined receiveAddress: undefined - isCrossAccountTrade?: boolean accountNumber: undefined quoteOrRate: 'rate' } diff --git a/src/components/MultiHopTrade/hooks/useGetTradeQuotes/getTradeQuoteInput.ts b/src/components/MultiHopTrade/hooks/useGetTradeQuotes/getTradeQuoteInput.ts index 6baa68423fc..8a576d4a96e 100644 --- a/src/components/MultiHopTrade/hooks/useGetTradeQuotes/getTradeQuoteInput.ts +++ b/src/components/MultiHopTrade/hooks/useGetTradeQuotes/getTradeQuoteInput.ts @@ -28,7 +28,6 @@ export type GetTradeQuoteInputArgs = { pubKey?: string | undefined quoteOrRate: 'quote' | 'rate' receiveAddress: string | undefined - isCrossAccountTrade?: boolean sellAccountNumber: number | undefined wallet: HDWallet | undefined } @@ -47,7 +46,6 @@ export const getTradeQuoteInput = async ({ potentialAffiliateBps, slippageTolerancePercentageDecimal, pubKey, - isCrossAccountTrade, }: GetTradeQuoteInputArgs): Promise => { const tradeQuoteInputCommonArgs: TradeQuoteInputCommonArgs = { sellAmountIncludingProtocolFeesCryptoBaseUnit: toBaseUnit( @@ -57,7 +55,6 @@ export const getTradeQuoteInput = async ({ sellAsset, buyAsset, receiveAddress, - isCrossAccountTrade, accountNumber: sellAccountNumber, affiliateBps: affiliateBps ?? '0', potentialAffiliateBps: potentialAffiliateBps ?? '0', diff --git a/src/components/MultiHopTrade/hooks/useGetTradeQuotes/useGetTradeQuotes.tsx b/src/components/MultiHopTrade/hooks/useGetTradeQuotes/useGetTradeQuotes.tsx index f293e13d1f6..278df5fcf23 100644 --- a/src/components/MultiHopTrade/hooks/useGetTradeQuotes/useGetTradeQuotes.tsx +++ b/src/components/MultiHopTrade/hooks/useGetTradeQuotes/useGetTradeQuotes.tsx @@ -276,7 +276,6 @@ export const useGetTradeQuotes = () => { wallet: wallet ?? undefined, quoteOrRate: 'quote', receiveAddress, - isCrossAccountTrade: Boolean(manualReceiveAddress), sellAmountBeforeFeesCryptoPrecision: sellAmountCryptoPrecision, allowMultiHop: true, affiliateBps, @@ -307,7 +306,6 @@ export const useGetTradeQuotes = () => { thorVotingPower, userSlippageTolerancePercentageDecimal, votingPower, - manualReceiveAddress, wallet, ]) diff --git a/src/components/MultiHopTrade/hooks/useGetTradeQuotes/useGetTradeRates.tsx b/src/components/MultiHopTrade/hooks/useGetTradeQuotes/useGetTradeRates.tsx index 778e17e367b..f9be0e39b44 100644 --- a/src/components/MultiHopTrade/hooks/useGetTradeQuotes/useGetTradeRates.tsx +++ b/src/components/MultiHopTrade/hooks/useGetTradeQuotes/useGetTradeRates.tsx @@ -224,7 +224,6 @@ export const useGetTradeRates = () => { allowMultiHop: true, affiliateBps, potentialAffiliateBps, - isCrossAccountTrade: Boolean(manualReceiveAddress), // Pass in the user's slippage preference if it's set, else let the swapper use its default slippageTolerancePercentageDecimal: userSlippageTolerancePercentageDecimal, pubKey: @@ -248,7 +247,6 @@ export const useGetTradeRates = () => { userSlippageTolerancePercentageDecimal, sellAssetUsdRate, sellAccountId, - manualReceiveAddress, isVotingPowerLoading, isBuyAssetChainSupported, receiveAddress, diff --git a/src/components/MultiHopTrade/types.ts b/src/components/MultiHopTrade/types.ts index c59d228664a..11aebb2aae9 100644 --- a/src/components/MultiHopTrade/types.ts +++ b/src/components/MultiHopTrade/types.ts @@ -26,7 +26,6 @@ export type TradeQuoteInputCommonArgs = Pick< | 'sellAsset' | 'buyAsset' | 'receiveAddress' - | 'isCrossAccountTrade' | 'accountNumber' | 'affiliateBps' | 'potentialAffiliateBps' diff --git a/src/state/apis/swapper/swapperApi.ts b/src/state/apis/swapper/swapperApi.ts index cbdc12ad855..66221add508 100644 --- a/src/state/apis/swapper/swapperApi.ts +++ b/src/state/apis/swapper/swapperApi.ts @@ -1,6 +1,6 @@ import { createApi } from '@reduxjs/toolkit/dist/query/react' import type { ChainId } from '@shapeshiftoss/caip' -import { type AssetId, fromAssetId } from '@shapeshiftoss/caip' +import { type AssetId, fromAssetId, solAssetId } from '@shapeshiftoss/caip' import type { GetTradeRateInput, SwapperConfig, SwapperDeps } from '@shapeshiftoss/swapper' import { getSupportedBuyAssetIds, @@ -56,11 +56,16 @@ export const swapperApi = createApi({ quoteOrRate, } = tradeQuoteInput + const isSolSellAssetId = sellAsset.assetId === solAssetId const isCrossAccountTrade = Boolean(sendAddress && receiveAddress) && sendAddress?.toLowerCase() !== receiveAddress?.toLowerCase() const featureFlags: FeatureFlags = selectFeatureFlags(state) - const isSwapperEnabled = getEnabledSwappers(featureFlags, isCrossAccountTrade)[swapperName] + const isSwapperEnabled = getEnabledSwappers( + featureFlags, + isCrossAccountTrade, + isSolSellAssetId, + )[swapperName] if (!isSwapperEnabled) return { data: {} } @@ -261,7 +266,7 @@ export const swapperApi = createApi({ const state = getState() as ReduxState const featureFlags = selectFeatureFlags(state) - const enabledSwappers = getEnabledSwappers(featureFlags, false) + const enabledSwappers = getEnabledSwappers(featureFlags, false, false) const assets = selectAssets(state) const sellAsset = selectInputSellAsset(state) const swapperConfig: SwapperConfig = getConfig() diff --git a/src/state/helpers.ts b/src/state/helpers.ts index ec53402e389..8a7ebabd000 100644 --- a/src/state/helpers.ts +++ b/src/state/helpers.ts @@ -34,6 +34,7 @@ export const getEnabledSwappers = ( JupiterSwap, }: FeatureFlags, isCrossAccountTrade: boolean, + isSolSellAssetId: boolean, ): Record => { return { [SwapperName.LIFI]: @@ -53,7 +54,9 @@ export const getEnabledSwappers = ( ChainflipSwap && (!isCrossAccountTrade || isCrossAccountTradeSupported(SwapperName.Chainflip)), [SwapperName.Jupiter]: - JupiterSwap && (!isCrossAccountTrade || isCrossAccountTradeSupported(SwapperName.Jupiter)), + JupiterSwap && + (!isCrossAccountTrade || + (isCrossAccountTradeSupported(SwapperName.Jupiter) && !isSolSellAssetId)), [SwapperName.Test]: false, } } diff --git a/src/state/slices/tradeQuoteSlice/selectors.ts b/src/state/slices/tradeQuoteSlice/selectors.ts index c47c8abb983..7cedc41d985 100644 --- a/src/state/slices/tradeQuoteSlice/selectors.ts +++ b/src/state/slices/tradeQuoteSlice/selectors.ts @@ -70,7 +70,7 @@ const selectEnabledSwappersIgnoringCrossAccountTrade = createSelector( selectFeatureFlags, featureFlags => { // cross account trade logic is irrelevant here, so we can set the flag to false here - const enabledSwappers = getEnabledSwappers(featureFlags, false) + const enabledSwappers = getEnabledSwappers(featureFlags, false, false) return Object.values(SwapperName).filter( swapperName => enabledSwappers[swapperName], ) as SwapperName[] From 9c66e614642dfa0f9d972d0b6d333294c3973807 Mon Sep 17 00:00:00 2001 From: NeOMakinG <14963751+NeOMakinG@users.noreply.github.com> Date: Tue, 26 Nov 2024 09:13:36 +0100 Subject: [PATCH 119/127] fix: review feedbacks --- src/state/apis/swapper/swapperApi.ts | 4 ++-- src/state/helpers.ts | 4 ++-- src/state/slices/tradeQuoteSlice/selectors.ts | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/state/apis/swapper/swapperApi.ts b/src/state/apis/swapper/swapperApi.ts index 66221add508..1e4f767d501 100644 --- a/src/state/apis/swapper/swapperApi.ts +++ b/src/state/apis/swapper/swapperApi.ts @@ -56,7 +56,7 @@ export const swapperApi = createApi({ quoteOrRate, } = tradeQuoteInput - const isSolSellAssetId = sellAsset.assetId === solAssetId + const isSolBuyAssetId = buyAsset.assetId === solAssetId const isCrossAccountTrade = Boolean(sendAddress && receiveAddress) && sendAddress?.toLowerCase() !== receiveAddress?.toLowerCase() @@ -64,7 +64,7 @@ export const swapperApi = createApi({ const isSwapperEnabled = getEnabledSwappers( featureFlags, isCrossAccountTrade, - isSolSellAssetId, + isSolBuyAssetId, )[swapperName] if (!isSwapperEnabled) return { data: {} } diff --git a/src/state/helpers.ts b/src/state/helpers.ts index 8a7ebabd000..c03af44fffd 100644 --- a/src/state/helpers.ts +++ b/src/state/helpers.ts @@ -34,7 +34,7 @@ export const getEnabledSwappers = ( JupiterSwap, }: FeatureFlags, isCrossAccountTrade: boolean, - isSolSellAssetId: boolean, + isSolBuyAssetId: boolean, ): Record => { return { [SwapperName.LIFI]: @@ -56,7 +56,7 @@ export const getEnabledSwappers = ( [SwapperName.Jupiter]: JupiterSwap && (!isCrossAccountTrade || - (isCrossAccountTradeSupported(SwapperName.Jupiter) && !isSolSellAssetId)), + (isCrossAccountTradeSupported(SwapperName.Jupiter) && !isSolBuyAssetId)), [SwapperName.Test]: false, } } diff --git a/src/state/slices/tradeQuoteSlice/selectors.ts b/src/state/slices/tradeQuoteSlice/selectors.ts index 7cedc41d985..c89951c20de 100644 --- a/src/state/slices/tradeQuoteSlice/selectors.ts +++ b/src/state/slices/tradeQuoteSlice/selectors.ts @@ -69,7 +69,7 @@ const selectTradeQuotes = createDeepEqualOutputSelector( const selectEnabledSwappersIgnoringCrossAccountTrade = createSelector( selectFeatureFlags, featureFlags => { - // cross account trade logic is irrelevant here, so we can set the flag to false here + // cross account trade logic is irrelevant here, so we can set the flags to false here const enabledSwappers = getEnabledSwappers(featureFlags, false, false) return Object.values(SwapperName).filter( swapperName => enabledSwappers[swapperName], From 0f1cbcdf5e3061feb0557e27eff508628b775745 Mon Sep 17 00:00:00 2001 From: NeOMakinG <14963751+NeOMakinG@users.noreply.github.com> Date: Tue, 26 Nov 2024 10:25:47 +0100 Subject: [PATCH 120/127] fix: instructions at quote time --- .../src/swappers/JupiterSwapper/endpoints.ts | 115 ++---------------- .../swapperApi/getTradeQuote.ts | 97 +++++++++++++-- packages/swapper/src/types.ts | 20 ++- 3 files changed, 113 insertions(+), 119 deletions(-) diff --git a/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts b/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts index 2b4cf925818..11a4740810d 100644 --- a/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts +++ b/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts @@ -1,16 +1,11 @@ -import { CHAIN_NAMESPACE, fromAssetId, solAssetId, wrappedSolAssetId } from '@shapeshiftoss/caip' -import type { BuildSendApiTxInput, GetFeeDataInput } from '@shapeshiftoss/chain-adapters' +import type { BuildSendApiTxInput } from '@shapeshiftoss/chain-adapters' import type { SolanaSignTx } from '@shapeshiftoss/hdwallet-core' import type { KnownChainIds } from '@shapeshiftoss/types' -import { PublicKey, type TransactionInstruction } from '@solana/web3.js' -import type { AxiosError } from 'axios' -import type { GetUnsignedSolanaTransactionArgs } from '../../types' -import { type SwapperApi } from '../../types' +import type { GetUnsignedSolanaTransactionArgs, SwapperApi } from '../../types' +import { isSolanaFeeData } from '../../types' import { checkSolanaSwapStatus, isExecutableTradeQuote, isExecutableTradeStep } from '../../utils' -import type { Instruction } from './models/Instruction' import { getTradeQuote, getTradeRate } from './swapperApi/getTradeQuote' -import { getJupiterSwapInstructions } from './utils/helpers' export const jupiterApi: SwapperApi = { getTradeQuote, @@ -19,121 +14,31 @@ export const jupiterApi: SwapperApi = { tradeQuote, from, assertGetSolanaChainAdapter, - config, }: GetUnsignedSolanaTransactionArgs): Promise => { if (!isExecutableTradeQuote(tradeQuote)) throw Error('Unable to execute trade') - const jupiterUrl = config.REACT_APP_JUPITER_API_URL - const step = tradeQuote.steps[0] - if (!isExecutableTradeStep(step)) throw Error('Unable to execute step') - - if (!tradeQuote.rawQuote) throw Error('Missing raw quote') - - const contractAddress = - step.buyAsset.assetId === solAssetId - ? undefined - : fromAssetId(step.buyAsset.assetId).assetReference - const adapter = assertGetSolanaChainAdapter(step.sellAsset.chainId) - const isCrossAccountTrade = tradeQuote.receiveAddress !== from - - if (isCrossAccountTrade && step.buyAsset.assetId === solAssetId) { - throw Error('Manual receive address is not supported for SOL') - } - - const { instruction: createTokenAccountInstruction, destinationTokenAccount } = - contractAddress && isCrossAccountTrade - ? await adapter.createAssociatedTokenAccountInstruction({ - from, - to: tradeQuote.receiveAddress, - tokenId: contractAddress, - }) - : { instruction: undefined, destinationTokenAccount: undefined } - - const maybeSwapResponse = await getJupiterSwapInstructions({ - apiUrl: jupiterUrl, - fromAddress: from, - toAddress: isCrossAccountTrade ? destinationTokenAccount?.toString() : undefined, - rawQuote: tradeQuote.rawQuote, - wrapAndUnwrapSol: step.buyAsset.assetId === wrappedSolAssetId ? false : true, - // Shared account is not supported for simple AMMs - useSharedAccounts: - tradeQuote.rawQuote.routePlan.length > 1 && isCrossAccountTrade ? true : false, - }) - - if (maybeSwapResponse.isErr()) { - const error = maybeSwapResponse.unwrapErr() - const cause = error.cause as AxiosError - throw Error(cause.response!.data.detail) - } - - const { data: swapResponse } = maybeSwapResponse.unwrap() - - const convertJupiterInstruction = (instruction: Instruction): TransactionInstruction => ({ - ...instruction, - keys: instruction.accounts.map(account => ({ - ...account, - pubkey: new PublicKey(account.pubkey), - })), - data: Buffer.from(instruction.data, 'base64'), - programId: new PublicKey(instruction.programId), - }) - - const instructions: TransactionInstruction[] = [ - ...swapResponse.setupInstructions.map(convertJupiterInstruction), - convertJupiterInstruction(swapResponse.swapInstruction), - ] - - if (createTokenAccountInstruction) { - instructions.unshift(createTokenAccountInstruction) - } - - if (swapResponse.cleanupInstruction) { - instructions.push(convertJupiterInstruction(swapResponse.cleanupInstruction)) - } - - const getFeeData = async () => { - const { chainNamespace } = fromAssetId(step.sellAsset.assetId) - - switch (chainNamespace) { - case CHAIN_NAMESPACE.Solana: { - const sellAdapter = assertGetSolanaChainAdapter(step.sellAsset.chainId) - const getFeeDataInput: GetFeeDataInput = { - to: '', - value: '0', - chainSpecific: { - from, - addressLookupTableAccounts: swapResponse.addressLookupTableAddresses, - instructions, - }, - } - return await sellAdapter.getFeeData(getFeeDataInput) - } - - default: - throw new Error('Unsupported chainNamespace') - } - } - - const { fast } = await getFeeData() + if (!isExecutableTradeStep(step)) throw Error('Unable to execute step') - const solanaInstructions = instructions.map(instruction => + const solanaInstructions = step.jupiterTransactionMetadata?.instructions?.map(instruction => adapter.convertInstruction(instruction), ) + if (!isSolanaFeeData(step.feeData.chainSpecific)) throw Error('Unable to execute step') + const buildSwapTxInput: BuildSendApiTxInput = { to: '', from, value: '0', accountNumber: step.accountNumber, chainSpecific: { - addressLookupTableAccounts: swapResponse.addressLookupTableAddresses, + addressLookupTableAccounts: step.jupiterTransactionMetadata?.addressLookupTableAddresses, instructions: solanaInstructions, - computeUnitLimit: fast.chainSpecific.computeUnits, - computeUnitPrice: fast.chainSpecific.priorityFee, + computeUnitLimit: step.feeData.chainSpecific?.computeUnits, + computeUnitPrice: step.feeData.chainSpecific?.priorityFee, }, } diff --git a/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeQuote.ts b/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeQuote.ts index e2e4eefa5f7..c01a9a0eed6 100644 --- a/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeQuote.ts +++ b/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeQuote.ts @@ -13,6 +13,8 @@ import type { KnownChainIds } from '@shapeshiftoss/types' import { bnOrZero, convertDecimalPercentageToBasisPoints } from '@shapeshiftoss/utils' import type { Result } from '@sniptt/monads' import { Err, Ok } from '@sniptt/monads' +import { PublicKey, type TransactionInstruction } from '@solana/web3.js' +import type { AxiosError } from 'axios' import { v4 as uuid } from 'uuid' import { getDefaultSlippageDecimalPercentageForSwapper } from '../../../constants' @@ -27,7 +29,8 @@ import type { } from '../../../types' import { SwapperName, TradeQuoteError } from '../../../types' import { getRate, makeSwapErrorRight } from '../../../utils' -import { getJupiterQuote, isSupportedChainId } from '../utils/helpers' +import type { Instruction } from '../models/Instruction' +import { getJupiterQuote, getJupiterSwapInstructions, isSupportedChainId } from '../utils/helpers' const _getTradeQuote = async ( input: CommonTradeQuoteInput, @@ -40,6 +43,7 @@ const _getTradeQuote = async ( affiliateBps, receiveAddress, accountNumber, + sendAddress, slippageTolerancePercentageDecimal, } = input @@ -67,6 +71,16 @@ const _getTradeQuote = async ( ) } + if (!sendAddress) { + return Err( + makeSwapErrorRight({ + message: `sendAddress is required`, + code: TradeQuoteError.UnknownError, + details: { chainId: sellAsset.chainId }, + }), + ) + } + const maybeQuoteResponse = await getJupiterQuote({ apiUrl: jupiterUrl, sourceAsset: sellAsset.assetId === solAssetId ? wrappedSolAssetId : sellAsset.assetId, @@ -90,6 +104,63 @@ const _getTradeQuote = async ( const { data: quoteResponse } = maybeQuoteResponse.unwrap() + const contractAddress = + buyAsset.assetId === solAssetId ? undefined : fromAssetId(buyAsset.assetId).assetReference + + const adapter = deps.assertGetSolanaChainAdapter(sellAsset.chainId) + + const isCrossAccountTrade = receiveAddress ? receiveAddress !== sendAddress : false + + const { instruction: createTokenAccountInstruction, destinationTokenAccount } = + contractAddress && isCrossAccountTrade + ? await adapter.createAssociatedTokenAccountInstruction({ + from: sendAddress, + to: receiveAddress, + tokenId: contractAddress, + }) + : { instruction: undefined, destinationTokenAccount: undefined } + + const maybeSwapResponse = await getJupiterSwapInstructions({ + apiUrl: jupiterUrl, + fromAddress: sendAddress, + toAddress: isCrossAccountTrade ? destinationTokenAccount?.toString() : undefined, + rawQuote: quoteResponse, + wrapAndUnwrapSol: buyAsset.assetId === wrappedSolAssetId ? false : true, + // Shared account is not supported for simple AMMs + useSharedAccounts: quoteResponse.routePlan.length > 1 && isCrossAccountTrade ? true : false, + }) + + if (maybeSwapResponse.isErr()) { + const error = maybeSwapResponse.unwrapErr() + const cause = error.cause as AxiosError + throw Error(cause.response!.data.detail) + } + + const { data: swapResponse } = maybeSwapResponse.unwrap() + + const convertJupiterInstruction = (instruction: Instruction): TransactionInstruction => ({ + ...instruction, + keys: instruction.accounts.map(account => ({ + ...account, + pubkey: new PublicKey(account.pubkey), + })), + data: Buffer.from(instruction.data, 'base64'), + programId: new PublicKey(instruction.programId), + }) + + const instructions: TransactionInstruction[] = [ + ...swapResponse.setupInstructions.map(convertJupiterInstruction), + convertJupiterInstruction(swapResponse.swapInstruction), + ] + + if (createTokenAccountInstruction) { + instructions.unshift(createTokenAccountInstruction) + } + + if (swapResponse.cleanupInstruction) { + instructions.push(convertJupiterInstruction(swapResponse.cleanupInstruction)) + } + const getFeeData = async () => { const { chainNamespace } = fromAssetId(sellAsset.assetId) @@ -97,18 +168,15 @@ const _getTradeQuote = async ( case CHAIN_NAMESPACE.Solana: { const sellAdapter = deps.assertGetSolanaChainAdapter(sellAsset.chainId) const getFeeDataInput: GetFeeDataInput = { - to: receiveAddress ?? input.sendAddress, - value: sellAmount, + to: '', + value: '0', chainSpecific: { - from: input.sendAddress!, - tokenId: - sellAsset.assetId === solAssetId - ? undefined - : fromAssetId(sellAsset.assetId).assetReference, + from: sendAddress, + addressLookupTableAccounts: swapResponse.addressLookupTableAddresses, + instructions, }, } - const { fast } = await sellAdapter.getFeeData(getFeeDataInput) - return { networkFeeCryptoBaseUnit: fast.txFee } + return await sellAdapter.getFeeData(getFeeDataInput) } default: @@ -162,7 +230,6 @@ const _getTradeQuote = async ( receiveAddress, potentialAffiliateBps: affiliateBps, affiliateBps, - rawQuote: quoteResponse, slippageTolerancePercentageDecimal: slippageTolerancePercentageDecimal ?? getDefaultSlippageDecimalPercentageForSwapper(SwapperName.Jupiter), @@ -171,9 +238,15 @@ const _getTradeQuote = async ( buyAmountBeforeFeesCryptoBaseUnit: quoteResponse.outAmount, buyAmountAfterFeesCryptoBaseUnit: quoteResponse.outAmount, sellAmountIncludingProtocolFeesCryptoBaseUnit: quoteResponse.inAmount, + jupiterQuoteResponse: quoteResponse, + jupiterTransactionMetadata: { + addressLookupTableAddresses: swapResponse.addressLookupTableAddresses, + instructions, + }, feeData: { protocolFees, - ...feeData, + networkFeeCryptoBaseUnit: feeData.fast.txFee, + chainSpecific: feeData.fast.chainSpecific, }, rate, source: SwapperName.Jupiter, diff --git a/packages/swapper/src/types.ts b/packages/swapper/src/types.ts index 46f36c8ff81..4997c299b58 100644 --- a/packages/swapper/src/types.ts +++ b/packages/swapper/src/types.ts @@ -21,6 +21,7 @@ import type { } from '@shapeshiftoss/types' import type { evm, TxStatus } from '@shapeshiftoss/unchained-client' import type { Result } from '@sniptt/monads' +import type { TransactionInstruction } from '@solana/web3.js' import type { TypedData } from 'eip-712' import type { InterpolationOptions } from 'node-polyglot' import type { Address } from 'viem' @@ -115,6 +116,11 @@ export type CosmosSdkFeeData = { estimatedGasCryptoBaseUnit: string } +export type SolanaFeeData = { + computeUnits: string + priorityFee: string +} + export type AmountDisplayMeta = { amountCryptoBaseUnit: string asset: Partial & Pick @@ -125,7 +131,13 @@ export type ProtocolFee = { requiresBalance: boolean } & AmountDisplayMeta export type QuoteFeeData = { networkFeeCryptoBaseUnit: string | undefined // fee paid to the network from the fee asset (undefined if unknown) protocolFees: PartialRecord // fee(s) paid to the protocol(s) - chainSpecific?: UtxoFeeData | CosmosSdkFeeData + chainSpecific?: UtxoFeeData | CosmosSdkFeeData | SolanaFeeData +} + +export const isSolanaFeeData = ( + chainSpecific: QuoteFeeData['chainSpecific'], +): chainSpecific is SolanaFeeData => { + return Boolean(chainSpecific && 'priorityFee' in chainSpecific) } export type BuyAssetBySellIdInput = { @@ -268,6 +280,11 @@ export type TradeQuoteStep = { gasLimit: string } cowswapQuoteResponse?: CowSwapQuoteResponse + jupiterQuoteResponse?: QuoteResponse + jupiterTransactionMetadata?: { + addressLookupTableAddresses: string[] + instructions?: TransactionInstruction[] + } } export type TradeRateStep = Omit & { accountNumber: undefined } @@ -282,7 +299,6 @@ type TradeQuoteBase = { isStreaming?: boolean slippageTolerancePercentageDecimal: string | undefined // undefined if slippage limit is not provided or specified by the swapper isLongtail?: boolean - rawQuote?: QuoteResponse } type TradeRateBase = Omit & { receiveAddress: undefined } From 0111088de1cb9d0cf46275e380b7bd5a5403fdc5 Mon Sep 17 00:00:00 2001 From: NeOMakinG <14963751+NeOMakinG@users.noreply.github.com> Date: Tue, 26 Nov 2024 11:27:12 +0100 Subject: [PATCH 121/127] fix: split rate and quote --- .../swapperApi/getTradeQuote.ts | 213 +++++++++++++++--- 1 file changed, 180 insertions(+), 33 deletions(-) diff --git a/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeQuote.ts b/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeQuote.ts index c01a9a0eed6..0c4adbddb9d 100644 --- a/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeQuote.ts +++ b/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeQuote.ts @@ -30,12 +30,15 @@ import type { import { SwapperName, TradeQuoteError } from '../../../types' import { getRate, makeSwapErrorRight } from '../../../utils' import type { Instruction } from '../models/Instruction' +import type { QuoteResponse } from '../models/QuoteResponse' import { getJupiterQuote, getJupiterSwapInstructions, isSupportedChainId } from '../utils/helpers' -const _getTradeQuote = async ( - input: CommonTradeQuoteInput, +const tradeQuoteMetadata: Map = new Map() + +export const getTradeRate = async ( + input: GetTradeRateInput, deps: SwapperDeps, -): Promise> => { +): Promise> => { const { sellAsset, buyAsset, @@ -104,6 +107,177 @@ const _getTradeQuote = async ( const { data: quoteResponse } = maybeQuoteResponse.unwrap() + tradeQuoteMetadata.set('rate', quoteResponse) + + const getFeeData = async () => { + const { chainNamespace } = fromAssetId(sellAsset.assetId) + + switch (chainNamespace) { + case CHAIN_NAMESPACE.Solana: { + const sellAdapter = deps.assertGetSolanaChainAdapter(sellAsset.chainId) + const getFeeDataInput: GetFeeDataInput = { + to: receiveAddress ?? sendAddress, + value: sellAmount, + chainSpecific: { + from: input.sendAddress!, + tokenId: + sellAsset.assetId === solAssetId + ? undefined + : fromAssetId(sellAsset.assetId).assetReference, + }, + } + const { fast } = await sellAdapter.getFeeData(getFeeDataInput) + return { networkFeeCryptoBaseUnit: fast.txFee } + } + + default: + throw new Error('Unsupported chainNamespace') + } + } + + const protocolFees: Record = quoteResponse.routePlan.reduce( + (acc, route) => { + const feeAssetId = toAssetId({ + assetReference: route.swapInfo.feeMint, + assetNamespace: ASSET_NAMESPACE.splToken, + chainNamespace: CHAIN_NAMESPACE.Solana, + chainReference: CHAIN_REFERENCE.SolanaMainnet, + }) + const feeAsset = assetsById[feeAssetId] + + // If we can't find the feeAsset, we can't provide a protocol fee to display + // But these fees exists at protocol level, it's mostly to make TS happy as we should have the market data and assets + if (!feeAsset) return acc + + acc[feeAssetId] = { + requiresBalance: false, + amountCryptoBaseUnit: bnOrZero(route.swapInfo.feeAmount).toFixed(0), + asset: feeAsset, + } + + return acc + }, + {} as Record, + ) + + const getQuoteRate = (sellAmountCryptoBaseUnit: string, buyAmountCryptoBaseUnit: string) => { + return getRate({ + sellAmountCryptoBaseUnit, + buyAmountCryptoBaseUnit, + sellAsset, + buyAsset, + }) + } + + const rates: TradeRate[] = [] + + const feeData = await getFeeData() + + const rate = getQuoteRate(quoteResponse.inAmount, quoteResponse.outAmount) + + const tradeRate: TradeRate = { + id: uuid(), + rate, + receiveAddress, + potentialAffiliateBps: affiliateBps, + affiliateBps, + accountNumber, + slippageTolerancePercentageDecimal: + slippageTolerancePercentageDecimal ?? + getDefaultSlippageDecimalPercentageForSwapper(SwapperName.Jupiter), + steps: [ + { + buyAmountBeforeFeesCryptoBaseUnit: quoteResponse.outAmount, + buyAmountAfterFeesCryptoBaseUnit: quoteResponse.outAmount, + sellAmountIncludingProtocolFeesCryptoBaseUnit: quoteResponse.inAmount, + jupiterQuoteResponse: quoteResponse, + feeData: { + protocolFees, + ...feeData, + }, + rate, + source: SwapperName.Jupiter, + buyAsset, + sellAsset, + accountNumber, + allowanceContract: '0x0', + estimatedExecutionTimeMs: quoteResponse.timeTaken! * 1000, + }, + ], + } + + rates.push(tradeRate) + + return Ok(rates) +} + +export const getTradeQuote = async ( + input: CommonTradeQuoteInput, + deps: SwapperDeps, +): Promise> => { + const { + sellAsset, + buyAsset, + affiliateBps, + receiveAddress, + accountNumber, + sendAddress, + slippageTolerancePercentageDecimal, + } = input + + const { assetsById } = deps + + const jupiterUrl = deps.config.REACT_APP_JUPITER_API_URL + + if (accountNumber === undefined) { + return Err( + makeSwapErrorRight({ + message: `accountNumber is required`, + code: TradeQuoteError.UnknownError, + }), + ) + } + + if (!isSupportedChainId(sellAsset.chainId)) { + return Err( + makeSwapErrorRight({ + message: `unsupported chainId`, + code: TradeQuoteError.UnsupportedChain, + details: { chainId: sellAsset.chainId }, + }), + ) + } + + if (!isSupportedChainId(buyAsset.chainId)) { + return Err( + makeSwapErrorRight({ + message: `unsupported chainId`, + code: TradeQuoteError.UnsupportedChain, + details: { chainId: sellAsset.chainId }, + }), + ) + } + + if (!sendAddress) { + return Err( + makeSwapErrorRight({ + message: `sendAddress is required`, + code: TradeQuoteError.UnknownError, + }), + ) + } + + const quoteResponse = tradeQuoteMetadata.get('rate') + + if (!quoteResponse) { + return Err( + makeSwapErrorRight({ + message: `quote not found`, + code: TradeQuoteError.UnknownError, + }), + ) + } + const contractAddress = buyAsset.assetId === solAssetId ? undefined : fromAssetId(buyAsset.assetId).assetReference @@ -115,7 +289,7 @@ const _getTradeQuote = async ( contractAddress && isCrossAccountTrade ? await adapter.createAssociatedTokenAccountInstruction({ from: sendAddress, - to: receiveAddress, + to: receiveAddress!, tokenId: contractAddress, }) : { instruction: undefined, destinationTokenAccount: undefined } @@ -227,14 +401,15 @@ const _getTradeQuote = async ( const tradeQuote: TradeQuote = { id: uuid(), rate, - receiveAddress, potentialAffiliateBps: affiliateBps, affiliateBps, + receiveAddress, slippageTolerancePercentageDecimal: slippageTolerancePercentageDecimal ?? getDefaultSlippageDecimalPercentageForSwapper(SwapperName.Jupiter), steps: [ { + accountNumber, buyAmountBeforeFeesCryptoBaseUnit: quoteResponse.outAmount, buyAmountAfterFeesCryptoBaseUnit: quoteResponse.outAmount, sellAmountIncludingProtocolFeesCryptoBaseUnit: quoteResponse.inAmount, @@ -252,7 +427,6 @@ const _getTradeQuote = async ( source: SwapperName.Jupiter, buyAsset, sellAsset, - accountNumber, allowanceContract: '0x0', estimatedExecutionTimeMs: quoteResponse.timeTaken! * 1000, }, @@ -263,30 +437,3 @@ const _getTradeQuote = async ( return Ok(quotes) } - -export const getTradeRate = async ( - input: GetTradeRateInput, - deps: SwapperDeps, -): Promise> => { - const rates = await _getTradeQuote(input as unknown as CommonTradeQuoteInput, deps) - return rates as Result -} - -export const getTradeQuote = async ( - input: CommonTradeQuoteInput, - deps: SwapperDeps, -): Promise> => { - const { accountNumber } = input - - if (accountNumber === undefined) { - return Err( - makeSwapErrorRight({ - message: `accountNumber is required`, - code: TradeQuoteError.UnknownError, - }), - ) - } - - const quotes = await _getTradeQuote(input, deps) - return quotes -} From 56e268fc4c4086305ed663271b2c65f4a1883572 Mon Sep 17 00:00:00 2001 From: NeOMakinG <14963751+NeOMakinG@users.noreply.github.com> Date: Tue, 26 Nov 2024 17:41:18 +0100 Subject: [PATCH 122/127] fix: review feedbacks --- packages/swapper/src/constants.ts | 2 +- .../src/swappers/JupiterSwapper/endpoints.ts | 432 ++++++++++++++++- .../swapperApi/getTradeQuote.ts | 439 ------------------ .../JupiterSwapper/utils/constants.ts | 5 + .../swappers/JupiterSwapper/utils/helpers.ts | 2 +- 5 files changed, 432 insertions(+), 448 deletions(-) delete mode 100644 packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeQuote.ts diff --git a/packages/swapper/src/constants.ts b/packages/swapper/src/constants.ts index e487c90adbb..7332700f2eb 100644 --- a/packages/swapper/src/constants.ts +++ b/packages/swapper/src/constants.ts @@ -105,7 +105,7 @@ const DEFAULT_LIFI_SLIPPAGE_DECIMAL_PERCENTAGE = '0.005' // .5% const DEFAULT_THOR_SLIPPAGE_DECIMAL_PERCENTAGE = '0.01' // 1% const DEFAULT_ARBITRUM_BRIDGE_SLIPPAGE_DECIMAL_PERCENTAGE = '0' // no slippage for Arbitrum Bridge, so no slippage tolerance const DEFAULT_CHAINFLIP_SLIPPAGE_DECIMAL_PERCENTAGE = '0.02' // 2% -const DEFAULT_JUPITER_SLIPPAGE_DECIMAL_PERCENTAGE = '0.005' // .5% +const DEFAULT_JUPITER_SLIPPAGE_DECIMAL_PERCENTAGE = '0.01' // .5% export const getDefaultSlippageDecimalPercentageForSwapper = ( swapperName?: SwapperName, diff --git a/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts b/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts index 11a4740810d..0facaa8321b 100644 --- a/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts +++ b/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts @@ -1,15 +1,433 @@ -import type { BuildSendApiTxInput } from '@shapeshiftoss/chain-adapters' +import type { AssetId } from '@shapeshiftoss/caip' +import { + ASSET_NAMESPACE, + CHAIN_NAMESPACE, + CHAIN_REFERENCE, + fromAssetId, + solAssetId, + toAssetId, + wrappedSolAssetId, +} from '@shapeshiftoss/caip' +import type { BuildSendApiTxInput, GetFeeDataInput } from '@shapeshiftoss/chain-adapters' import type { SolanaSignTx } from '@shapeshiftoss/hdwallet-core' import type { KnownChainIds } from '@shapeshiftoss/types' +import { bnOrZero, convertDecimalPercentageToBasisPoints } from '@shapeshiftoss/utils' +import type { Result } from '@sniptt/monads' +import { Err, Ok } from '@sniptt/monads' +import { PublicKey, type TransactionInstruction } from '@solana/web3.js' +import type { AxiosError } from 'axios' +import { v4 as uuid } from 'uuid' -import type { GetUnsignedSolanaTransactionArgs, SwapperApi } from '../../types' -import { isSolanaFeeData } from '../../types' -import { checkSolanaSwapStatus, isExecutableTradeQuote, isExecutableTradeStep } from '../../utils' -import { getTradeQuote, getTradeRate } from './swapperApi/getTradeQuote' +import { getDefaultSlippageDecimalPercentageForSwapper } from '../../constants' +import type { + CommonTradeQuoteInput, + GetTradeRateInput, + GetUnsignedSolanaTransactionArgs, + ProtocolFee, + SwapErrorRight, + SwapperApi, + SwapperDeps, + TradeQuote, + TradeRate, +} from '../../types' +import { isSolanaFeeData, SwapperName, TradeQuoteError } from '../../types' +import { + checkSolanaSwapStatus, + getRate, + isExecutableTradeQuote, + isExecutableTradeStep, + makeSwapErrorRight, +} from '../../utils' +import type { Instruction } from './models/Instruction' +import type { QuoteResponse } from './models/QuoteResponse' +import { JUPITER_COMPUTE_UNIT_MARGIN_PERCENT, SOLANA_RANDOM_ADDRESS } from './utils/constants' +import { getJupiterPrice, getJupiterSwapInstructions, isSupportedChainId } from './utils/helpers' + +const tradeQuoteMetadata: Map = new Map() export const jupiterApi: SwapperApi = { - getTradeQuote, - getTradeRate, + getTradeRate: async ( + input: GetTradeRateInput, + deps: SwapperDeps, + ): Promise> => { + const { + sellAsset, + buyAsset, + sellAmountIncludingProtocolFeesCryptoBaseUnit: sellAmount, + affiliateBps, + receiveAddress, + accountNumber, + slippageTolerancePercentageDecimal, + } = input + + const { assetsById } = deps + + const jupiterUrl = deps.config.REACT_APP_JUPITER_API_URL + + if (!isSupportedChainId(sellAsset.chainId)) { + return Err( + makeSwapErrorRight({ + message: `unsupported chainId`, + code: TradeQuoteError.UnsupportedChain, + details: { chainId: sellAsset.chainId }, + }), + ) + } + + if (!isSupportedChainId(buyAsset.chainId)) { + return Err( + makeSwapErrorRight({ + message: `unsupported chainId`, + code: TradeQuoteError.UnsupportedChain, + details: { chainId: sellAsset.chainId }, + }), + ) + } + + const maybePriceResponse = await getJupiterPrice({ + apiUrl: jupiterUrl, + sourceAsset: sellAsset.assetId === solAssetId ? wrappedSolAssetId : sellAsset.assetId, + destinationAsset: buyAsset.assetId === solAssetId ? wrappedSolAssetId : buyAsset.assetId, + commissionBps: affiliateBps, + amount: sellAmount, + slippageBps: convertDecimalPercentageToBasisPoints( + slippageTolerancePercentageDecimal ?? + getDefaultSlippageDecimalPercentageForSwapper(SwapperName.Jupiter), + ).toFixed(), + }) + + if (maybePriceResponse.isErr()) { + return Err( + makeSwapErrorRight({ + message: 'Quote request failed', + code: TradeQuoteError.NoRouteFound, + }), + ) + } + + const { data: quoteResponse } = maybePriceResponse.unwrap() + + tradeQuoteMetadata.set('rate', quoteResponse) + + const getFeeData = async () => { + const sellAdapter = deps.assertGetSolanaChainAdapter(sellAsset.chainId) + const getFeeDataInput: GetFeeDataInput = { + // used as a placeholder for the sake of loosely estimating fees + to: SOLANA_RANDOM_ADDRESS, + value: sellAmount, + chainSpecific: { + from: SOLANA_RANDOM_ADDRESS, + tokenId: + sellAsset.assetId === solAssetId + ? undefined + : fromAssetId(sellAsset.assetId).assetReference, + }, + } + const { fast } = await sellAdapter.getFeeData(getFeeDataInput) + return { networkFeeCryptoBaseUnit: fast.txFee } + } + + const protocolFees: Record = quoteResponse.routePlan.reduce( + (acc, route) => { + const feeAssetId = toAssetId({ + assetReference: route.swapInfo.feeMint, + assetNamespace: ASSET_NAMESPACE.splToken, + chainNamespace: CHAIN_NAMESPACE.Solana, + chainReference: CHAIN_REFERENCE.SolanaMainnet, + }) + const feeAsset = assetsById[feeAssetId] + + // If we can't find the feeAsset, we can't provide a protocol fee to display + // But these fees exists at protocol level, it's mostly to make TS happy as we should have the market data and assets + if (!feeAsset) return acc + + acc[feeAssetId] = { + requiresBalance: false, + amountCryptoBaseUnit: bnOrZero(route.swapInfo.feeAmount).toFixed(0), + asset: feeAsset, + } + + return acc + }, + {} as Record, + ) + + const getQuoteRate = (sellAmountCryptoBaseUnit: string, buyAmountCryptoBaseUnit: string) => { + return getRate({ + sellAmountCryptoBaseUnit, + buyAmountCryptoBaseUnit, + sellAsset, + buyAsset, + }) + } + + const rates: TradeRate[] = [] + + const feeData = await getFeeData() + + const rate = getQuoteRate(quoteResponse.inAmount, quoteResponse.outAmount) + + const tradeRate: TradeRate = { + id: uuid(), + rate, + receiveAddress, + potentialAffiliateBps: affiliateBps, + affiliateBps, + accountNumber, + slippageTolerancePercentageDecimal: + slippageTolerancePercentageDecimal ?? + getDefaultSlippageDecimalPercentageForSwapper(SwapperName.Jupiter), + steps: [ + { + buyAmountBeforeFeesCryptoBaseUnit: quoteResponse.outAmount, + buyAmountAfterFeesCryptoBaseUnit: quoteResponse.outAmount, + sellAmountIncludingProtocolFeesCryptoBaseUnit: quoteResponse.inAmount, + jupiterQuoteResponse: quoteResponse, + feeData: { + protocolFees, + ...feeData, + }, + rate, + source: SwapperName.Jupiter, + buyAsset, + sellAsset, + accountNumber, + allowanceContract: '0x0', + estimatedExecutionTimeMs: quoteResponse.timeTaken! * 1000, + }, + ], + } + + rates.push(tradeRate) + + return Ok(rates) + }, + getTradeQuote: async ( + input: CommonTradeQuoteInput, + deps: SwapperDeps, + ): Promise> => { + const { + sellAsset, + buyAsset, + affiliateBps, + receiveAddress, + accountNumber, + sendAddress, + slippageTolerancePercentageDecimal, + } = input + + const { assetsById } = deps + + const jupiterUrl = deps.config.REACT_APP_JUPITER_API_URL + + if (accountNumber === undefined) { + return Err( + makeSwapErrorRight({ + message: `accountNumber is required`, + code: TradeQuoteError.UnknownError, + }), + ) + } + + if (!isSupportedChainId(sellAsset.chainId)) { + return Err( + makeSwapErrorRight({ + message: `unsupported chainId`, + code: TradeQuoteError.UnsupportedChain, + details: { chainId: sellAsset.chainId }, + }), + ) + } + + if (!isSupportedChainId(buyAsset.chainId)) { + return Err( + makeSwapErrorRight({ + message: `unsupported chainId`, + code: TradeQuoteError.UnsupportedChain, + details: { chainId: sellAsset.chainId }, + }), + ) + } + + if (!sendAddress) { + return Err( + makeSwapErrorRight({ + message: `sendAddress is required`, + code: TradeQuoteError.UnknownError, + }), + ) + } + + const quoteResponse = tradeQuoteMetadata.get('rate') + + if (!quoteResponse) { + return Err( + makeSwapErrorRight({ + message: `quote not found`, + code: TradeQuoteError.UnknownError, + }), + ) + } + + const contractAddress = + buyAsset.assetId === solAssetId ? undefined : fromAssetId(buyAsset.assetId).assetReference + + const adapter = deps.assertGetSolanaChainAdapter(sellAsset.chainId) + + const isCrossAccountTrade = receiveAddress ? receiveAddress !== sendAddress : false + + const { instruction: createTokenAccountInstruction, destinationTokenAccount } = + contractAddress && isCrossAccountTrade + ? await adapter.createAssociatedTokenAccountInstruction({ + from: sendAddress, + to: receiveAddress!, + tokenId: contractAddress, + }) + : { instruction: undefined, destinationTokenAccount: undefined } + + const maybeSwapResponse = await getJupiterSwapInstructions({ + apiUrl: jupiterUrl, + fromAddress: sendAddress, + toAddress: isCrossAccountTrade ? destinationTokenAccount?.toString() : undefined, + rawQuote: quoteResponse, + wrapAndUnwrapSol: buyAsset.assetId === wrappedSolAssetId ? false : true, + // Shared account is not supported for simple AMMs + useSharedAccounts: quoteResponse.routePlan.length > 1 && isCrossAccountTrade ? true : false, + }) + + if (maybeSwapResponse.isErr()) { + const error = maybeSwapResponse.unwrapErr() + const cause = error.cause as AxiosError + throw Error(cause.response!.data.detail) + } + + const { data: swapResponse } = maybeSwapResponse.unwrap() + + const convertJupiterInstruction = (instruction: Instruction): TransactionInstruction => ({ + ...instruction, + keys: instruction.accounts.map(account => ({ + ...account, + pubkey: new PublicKey(account.pubkey), + })), + data: Buffer.from(instruction.data, 'base64'), + programId: new PublicKey(instruction.programId), + }) + + const instructions: TransactionInstruction[] = [ + ...swapResponse.setupInstructions.map(convertJupiterInstruction), + convertJupiterInstruction(swapResponse.swapInstruction), + ] + + if (createTokenAccountInstruction) { + instructions.unshift(createTokenAccountInstruction) + } + + if (swapResponse.cleanupInstruction) { + instructions.push(convertJupiterInstruction(swapResponse.cleanupInstruction)) + } + + const getFeeData = async () => { + const sellAdapter = deps.assertGetSolanaChainAdapter(sellAsset.chainId) + const getFeeDataInput: GetFeeDataInput = { + to: '', + value: '0', + chainSpecific: { + from: sendAddress, + addressLookupTableAccounts: swapResponse.addressLookupTableAddresses, + instructions, + }, + } + const feeData = await sellAdapter.getFeeData(getFeeDataInput) + return { + txFee: feeData.fast.txFee, + chainSpecific: { + computeUnits: bnOrZero(feeData.fast.chainSpecific.computeUnits) + .times(JUPITER_COMPUTE_UNIT_MARGIN_PERCENT) + .toFixed(0), + priorityFee: feeData.fast.chainSpecific.priorityFee, + }, + } + } + + const protocolFees: Record = quoteResponse.routePlan.reduce( + (acc, route) => { + const feeAssetId = toAssetId({ + assetReference: route.swapInfo.feeMint, + assetNamespace: ASSET_NAMESPACE.splToken, + chainNamespace: CHAIN_NAMESPACE.Solana, + chainReference: CHAIN_REFERENCE.SolanaMainnet, + }) + const feeAsset = assetsById[feeAssetId] + + // If we can't find the feeAsset, we can't provide a protocol fee to display + // But these fees exists at protocol level, it's mostly to make TS happy as we should have the market data and assets + if (!feeAsset) return acc + + acc[feeAssetId] = { + requiresBalance: false, + amountCryptoBaseUnit: bnOrZero(route.swapInfo.feeAmount).toFixed(0), + asset: feeAsset, + } + + return acc + }, + {} as Record, + ) + + const getQuoteRate = (sellAmountCryptoBaseUnit: string, buyAmountCryptoBaseUnit: string) => { + return getRate({ + sellAmountCryptoBaseUnit, + buyAmountCryptoBaseUnit, + sellAsset, + buyAsset, + }) + } + + const quotes: TradeQuote[] = [] + + const feeData = await getFeeData() + + const rate = getQuoteRate(quoteResponse.inAmount, quoteResponse.outAmount) + + const tradeQuote: TradeQuote = { + id: uuid(), + rate, + potentialAffiliateBps: affiliateBps, + affiliateBps, + receiveAddress, + slippageTolerancePercentageDecimal: + slippageTolerancePercentageDecimal ?? + getDefaultSlippageDecimalPercentageForSwapper(SwapperName.Jupiter), + steps: [ + { + accountNumber, + buyAmountBeforeFeesCryptoBaseUnit: quoteResponse.outAmount, + buyAmountAfterFeesCryptoBaseUnit: quoteResponse.outAmount, + sellAmountIncludingProtocolFeesCryptoBaseUnit: quoteResponse.inAmount, + jupiterQuoteResponse: quoteResponse, + jupiterTransactionMetadata: { + addressLookupTableAddresses: swapResponse.addressLookupTableAddresses, + instructions, + }, + feeData: { + protocolFees, + networkFeeCryptoBaseUnit: feeData.txFee, + chainSpecific: feeData.chainSpecific, + }, + rate, + source: SwapperName.Jupiter, + buyAsset, + sellAsset, + allowanceContract: '0x0', + estimatedExecutionTimeMs: quoteResponse.timeTaken! * 1000, + }, + ], + } + + quotes.push(tradeQuote) + + return Ok(quotes) + }, getUnsignedSolanaTransaction: async ({ tradeQuote, from, diff --git a/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeQuote.ts b/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeQuote.ts deleted file mode 100644 index 0c4adbddb9d..00000000000 --- a/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeQuote.ts +++ /dev/null @@ -1,439 +0,0 @@ -import type { AssetId } from '@shapeshiftoss/caip' -import { - ASSET_NAMESPACE, - CHAIN_NAMESPACE, - CHAIN_REFERENCE, - fromAssetId, - solAssetId, - toAssetId, - wrappedSolAssetId, -} from '@shapeshiftoss/caip' -import type { GetFeeDataInput } from '@shapeshiftoss/chain-adapters' -import type { KnownChainIds } from '@shapeshiftoss/types' -import { bnOrZero, convertDecimalPercentageToBasisPoints } from '@shapeshiftoss/utils' -import type { Result } from '@sniptt/monads' -import { Err, Ok } from '@sniptt/monads' -import { PublicKey, type TransactionInstruction } from '@solana/web3.js' -import type { AxiosError } from 'axios' -import { v4 as uuid } from 'uuid' - -import { getDefaultSlippageDecimalPercentageForSwapper } from '../../../constants' -import type { - CommonTradeQuoteInput, - GetTradeRateInput, - ProtocolFee, - SwapErrorRight, - SwapperDeps, - TradeQuote, - TradeRate, -} from '../../../types' -import { SwapperName, TradeQuoteError } from '../../../types' -import { getRate, makeSwapErrorRight } from '../../../utils' -import type { Instruction } from '../models/Instruction' -import type { QuoteResponse } from '../models/QuoteResponse' -import { getJupiterQuote, getJupiterSwapInstructions, isSupportedChainId } from '../utils/helpers' - -const tradeQuoteMetadata: Map = new Map() - -export const getTradeRate = async ( - input: GetTradeRateInput, - deps: SwapperDeps, -): Promise> => { - const { - sellAsset, - buyAsset, - sellAmountIncludingProtocolFeesCryptoBaseUnit: sellAmount, - affiliateBps, - receiveAddress, - accountNumber, - sendAddress, - slippageTolerancePercentageDecimal, - } = input - - const { assetsById } = deps - - const jupiterUrl = deps.config.REACT_APP_JUPITER_API_URL - - if (!isSupportedChainId(sellAsset.chainId)) { - return Err( - makeSwapErrorRight({ - message: `unsupported chainId`, - code: TradeQuoteError.UnsupportedChain, - details: { chainId: sellAsset.chainId }, - }), - ) - } - - if (!isSupportedChainId(buyAsset.chainId)) { - return Err( - makeSwapErrorRight({ - message: `unsupported chainId`, - code: TradeQuoteError.UnsupportedChain, - details: { chainId: sellAsset.chainId }, - }), - ) - } - - if (!sendAddress) { - return Err( - makeSwapErrorRight({ - message: `sendAddress is required`, - code: TradeQuoteError.UnknownError, - details: { chainId: sellAsset.chainId }, - }), - ) - } - - const maybeQuoteResponse = await getJupiterQuote({ - apiUrl: jupiterUrl, - sourceAsset: sellAsset.assetId === solAssetId ? wrappedSolAssetId : sellAsset.assetId, - destinationAsset: buyAsset.assetId === solAssetId ? wrappedSolAssetId : buyAsset.assetId, - commissionBps: affiliateBps, - amount: sellAmount, - slippageBps: convertDecimalPercentageToBasisPoints( - slippageTolerancePercentageDecimal ?? - getDefaultSlippageDecimalPercentageForSwapper(SwapperName.Jupiter), - ).toFixed(), - }) - - if (maybeQuoteResponse.isErr()) { - return Err( - makeSwapErrorRight({ - message: 'Quote request failed', - code: TradeQuoteError.NoRouteFound, - }), - ) - } - - const { data: quoteResponse } = maybeQuoteResponse.unwrap() - - tradeQuoteMetadata.set('rate', quoteResponse) - - const getFeeData = async () => { - const { chainNamespace } = fromAssetId(sellAsset.assetId) - - switch (chainNamespace) { - case CHAIN_NAMESPACE.Solana: { - const sellAdapter = deps.assertGetSolanaChainAdapter(sellAsset.chainId) - const getFeeDataInput: GetFeeDataInput = { - to: receiveAddress ?? sendAddress, - value: sellAmount, - chainSpecific: { - from: input.sendAddress!, - tokenId: - sellAsset.assetId === solAssetId - ? undefined - : fromAssetId(sellAsset.assetId).assetReference, - }, - } - const { fast } = await sellAdapter.getFeeData(getFeeDataInput) - return { networkFeeCryptoBaseUnit: fast.txFee } - } - - default: - throw new Error('Unsupported chainNamespace') - } - } - - const protocolFees: Record = quoteResponse.routePlan.reduce( - (acc, route) => { - const feeAssetId = toAssetId({ - assetReference: route.swapInfo.feeMint, - assetNamespace: ASSET_NAMESPACE.splToken, - chainNamespace: CHAIN_NAMESPACE.Solana, - chainReference: CHAIN_REFERENCE.SolanaMainnet, - }) - const feeAsset = assetsById[feeAssetId] - - // If we can't find the feeAsset, we can't provide a protocol fee to display - // But these fees exists at protocol level, it's mostly to make TS happy as we should have the market data and assets - if (!feeAsset) return acc - - acc[feeAssetId] = { - requiresBalance: false, - amountCryptoBaseUnit: bnOrZero(route.swapInfo.feeAmount).toFixed(0), - asset: feeAsset, - } - - return acc - }, - {} as Record, - ) - - const getQuoteRate = (sellAmountCryptoBaseUnit: string, buyAmountCryptoBaseUnit: string) => { - return getRate({ - sellAmountCryptoBaseUnit, - buyAmountCryptoBaseUnit, - sellAsset, - buyAsset, - }) - } - - const rates: TradeRate[] = [] - - const feeData = await getFeeData() - - const rate = getQuoteRate(quoteResponse.inAmount, quoteResponse.outAmount) - - const tradeRate: TradeRate = { - id: uuid(), - rate, - receiveAddress, - potentialAffiliateBps: affiliateBps, - affiliateBps, - accountNumber, - slippageTolerancePercentageDecimal: - slippageTolerancePercentageDecimal ?? - getDefaultSlippageDecimalPercentageForSwapper(SwapperName.Jupiter), - steps: [ - { - buyAmountBeforeFeesCryptoBaseUnit: quoteResponse.outAmount, - buyAmountAfterFeesCryptoBaseUnit: quoteResponse.outAmount, - sellAmountIncludingProtocolFeesCryptoBaseUnit: quoteResponse.inAmount, - jupiterQuoteResponse: quoteResponse, - feeData: { - protocolFees, - ...feeData, - }, - rate, - source: SwapperName.Jupiter, - buyAsset, - sellAsset, - accountNumber, - allowanceContract: '0x0', - estimatedExecutionTimeMs: quoteResponse.timeTaken! * 1000, - }, - ], - } - - rates.push(tradeRate) - - return Ok(rates) -} - -export const getTradeQuote = async ( - input: CommonTradeQuoteInput, - deps: SwapperDeps, -): Promise> => { - const { - sellAsset, - buyAsset, - affiliateBps, - receiveAddress, - accountNumber, - sendAddress, - slippageTolerancePercentageDecimal, - } = input - - const { assetsById } = deps - - const jupiterUrl = deps.config.REACT_APP_JUPITER_API_URL - - if (accountNumber === undefined) { - return Err( - makeSwapErrorRight({ - message: `accountNumber is required`, - code: TradeQuoteError.UnknownError, - }), - ) - } - - if (!isSupportedChainId(sellAsset.chainId)) { - return Err( - makeSwapErrorRight({ - message: `unsupported chainId`, - code: TradeQuoteError.UnsupportedChain, - details: { chainId: sellAsset.chainId }, - }), - ) - } - - if (!isSupportedChainId(buyAsset.chainId)) { - return Err( - makeSwapErrorRight({ - message: `unsupported chainId`, - code: TradeQuoteError.UnsupportedChain, - details: { chainId: sellAsset.chainId }, - }), - ) - } - - if (!sendAddress) { - return Err( - makeSwapErrorRight({ - message: `sendAddress is required`, - code: TradeQuoteError.UnknownError, - }), - ) - } - - const quoteResponse = tradeQuoteMetadata.get('rate') - - if (!quoteResponse) { - return Err( - makeSwapErrorRight({ - message: `quote not found`, - code: TradeQuoteError.UnknownError, - }), - ) - } - - const contractAddress = - buyAsset.assetId === solAssetId ? undefined : fromAssetId(buyAsset.assetId).assetReference - - const adapter = deps.assertGetSolanaChainAdapter(sellAsset.chainId) - - const isCrossAccountTrade = receiveAddress ? receiveAddress !== sendAddress : false - - const { instruction: createTokenAccountInstruction, destinationTokenAccount } = - contractAddress && isCrossAccountTrade - ? await adapter.createAssociatedTokenAccountInstruction({ - from: sendAddress, - to: receiveAddress!, - tokenId: contractAddress, - }) - : { instruction: undefined, destinationTokenAccount: undefined } - - const maybeSwapResponse = await getJupiterSwapInstructions({ - apiUrl: jupiterUrl, - fromAddress: sendAddress, - toAddress: isCrossAccountTrade ? destinationTokenAccount?.toString() : undefined, - rawQuote: quoteResponse, - wrapAndUnwrapSol: buyAsset.assetId === wrappedSolAssetId ? false : true, - // Shared account is not supported for simple AMMs - useSharedAccounts: quoteResponse.routePlan.length > 1 && isCrossAccountTrade ? true : false, - }) - - if (maybeSwapResponse.isErr()) { - const error = maybeSwapResponse.unwrapErr() - const cause = error.cause as AxiosError - throw Error(cause.response!.data.detail) - } - - const { data: swapResponse } = maybeSwapResponse.unwrap() - - const convertJupiterInstruction = (instruction: Instruction): TransactionInstruction => ({ - ...instruction, - keys: instruction.accounts.map(account => ({ - ...account, - pubkey: new PublicKey(account.pubkey), - })), - data: Buffer.from(instruction.data, 'base64'), - programId: new PublicKey(instruction.programId), - }) - - const instructions: TransactionInstruction[] = [ - ...swapResponse.setupInstructions.map(convertJupiterInstruction), - convertJupiterInstruction(swapResponse.swapInstruction), - ] - - if (createTokenAccountInstruction) { - instructions.unshift(createTokenAccountInstruction) - } - - if (swapResponse.cleanupInstruction) { - instructions.push(convertJupiterInstruction(swapResponse.cleanupInstruction)) - } - - const getFeeData = async () => { - const { chainNamespace } = fromAssetId(sellAsset.assetId) - - switch (chainNamespace) { - case CHAIN_NAMESPACE.Solana: { - const sellAdapter = deps.assertGetSolanaChainAdapter(sellAsset.chainId) - const getFeeDataInput: GetFeeDataInput = { - to: '', - value: '0', - chainSpecific: { - from: sendAddress, - addressLookupTableAccounts: swapResponse.addressLookupTableAddresses, - instructions, - }, - } - return await sellAdapter.getFeeData(getFeeDataInput) - } - - default: - throw new Error('Unsupported chainNamespace') - } - } - - const protocolFees: Record = quoteResponse.routePlan.reduce( - (acc, route) => { - const feeAssetId = toAssetId({ - assetReference: route.swapInfo.feeMint, - assetNamespace: ASSET_NAMESPACE.splToken, - chainNamespace: CHAIN_NAMESPACE.Solana, - chainReference: CHAIN_REFERENCE.SolanaMainnet, - }) - const feeAsset = assetsById[feeAssetId] - - // If we can't find the feeAsset, we can't provide a protocol fee to display - // But these fees exists at protocol level, it's mostly to make TS happy as we should have the market data and assets - if (!feeAsset) return acc - - acc[feeAssetId] = { - requiresBalance: false, - amountCryptoBaseUnit: bnOrZero(route.swapInfo.feeAmount).toFixed(0), - asset: feeAsset, - } - - return acc - }, - {} as Record, - ) - - const getQuoteRate = (sellAmountCryptoBaseUnit: string, buyAmountCryptoBaseUnit: string) => { - return getRate({ - sellAmountCryptoBaseUnit, - buyAmountCryptoBaseUnit, - sellAsset, - buyAsset, - }) - } - - const quotes: TradeQuote[] = [] - - const feeData = await getFeeData() - - const rate = getQuoteRate(quoteResponse.inAmount, quoteResponse.outAmount) - - const tradeQuote: TradeQuote = { - id: uuid(), - rate, - potentialAffiliateBps: affiliateBps, - affiliateBps, - receiveAddress, - slippageTolerancePercentageDecimal: - slippageTolerancePercentageDecimal ?? - getDefaultSlippageDecimalPercentageForSwapper(SwapperName.Jupiter), - steps: [ - { - accountNumber, - buyAmountBeforeFeesCryptoBaseUnit: quoteResponse.outAmount, - buyAmountAfterFeesCryptoBaseUnit: quoteResponse.outAmount, - sellAmountIncludingProtocolFeesCryptoBaseUnit: quoteResponse.inAmount, - jupiterQuoteResponse: quoteResponse, - jupiterTransactionMetadata: { - addressLookupTableAddresses: swapResponse.addressLookupTableAddresses, - instructions, - }, - feeData: { - protocolFees, - networkFeeCryptoBaseUnit: feeData.fast.txFee, - chainSpecific: feeData.fast.chainSpecific, - }, - rate, - source: SwapperName.Jupiter, - buyAsset, - sellAsset, - allowanceContract: '0x0', - estimatedExecutionTimeMs: quoteResponse.timeTaken! * 1000, - }, - ], - } - - quotes.push(tradeQuote) - - return Ok(quotes) -} diff --git a/packages/swapper/src/swappers/JupiterSwapper/utils/constants.ts b/packages/swapper/src/swappers/JupiterSwapper/utils/constants.ts index 37b3987a56d..99803b905ed 100644 --- a/packages/swapper/src/swappers/JupiterSwapper/utils/constants.ts +++ b/packages/swapper/src/swappers/JupiterSwapper/utils/constants.ts @@ -9,3 +9,8 @@ export const JUPITER_SUPPORTED_CHAIN_IDS: SupportedChainIds = { sell: jupiterSupportedChainIds, buy: jupiterSupportedChainIds, } + +export const SOLANA_RANDOM_ADDRESS = '2zHKF6tqam3tnNFPK2E9nBDkV7GMXnvdJautmzqQdn8A' + +// Jupiter use 40% as a compute unit margin while calculating them, some TX reverts without this +export const JUPITER_COMPUTE_UNIT_MARGIN_PERCENT = 1.4 diff --git a/packages/swapper/src/swappers/JupiterSwapper/utils/helpers.ts b/packages/swapper/src/swappers/JupiterSwapper/utils/helpers.ts index 272c93d244b..b8ee46e53a4 100644 --- a/packages/swapper/src/swappers/JupiterSwapper/utils/helpers.ts +++ b/packages/swapper/src/swappers/JupiterSwapper/utils/helpers.ts @@ -33,7 +33,7 @@ type GetJupiterSwapArgs = { wrapAndUnwrapSol: boolean } -export const getJupiterQuote = ({ +export const getJupiterPrice = ({ apiUrl, sourceAsset, destinationAsset, From 6978cacf4305b26049bfe5017f550867a4bb3f07 Mon Sep 17 00:00:00 2001 From: NeOMakinG <14963751+NeOMakinG@users.noreply.github.com> Date: Wed, 27 Nov 2024 13:42:23 +0100 Subject: [PATCH 123/127] fix: review feedbacks --- package.json | 1 + packages/swapper/src/constants.ts | 2 +- .../src/swappers/JupiterSwapper/endpoints.ts | 16 +- .../JupiterSwapper/models/AccountMeta.ts | 84 -------- .../JupiterSwapper/models/Instruction.ts | 91 --------- .../JupiterSwapper/models/PlatformFee.ts | 73 ------- .../JupiterSwapper/models/QuoteResponse.ts | 189 ------------------ .../JupiterSwapper/models/RoutePlanStep.ts | 82 -------- .../JupiterSwapper/models/SwapInfo.ts | 128 ------------ .../models/SwapInstructionsResponse.ts | 116 ----------- .../JupiterSwapper/models/SwapMode.ts | 38 ---- .../JupiterSwapper/utils/constants.ts | 2 +- .../swappers/JupiterSwapper/utils/helpers.ts | 3 +- packages/swapper/src/types.ts | 2 +- yarn.lock | 8 + 15 files changed, 25 insertions(+), 810 deletions(-) delete mode 100644 packages/swapper/src/swappers/JupiterSwapper/models/AccountMeta.ts delete mode 100644 packages/swapper/src/swappers/JupiterSwapper/models/Instruction.ts delete mode 100644 packages/swapper/src/swappers/JupiterSwapper/models/PlatformFee.ts delete mode 100644 packages/swapper/src/swappers/JupiterSwapper/models/QuoteResponse.ts delete mode 100644 packages/swapper/src/swappers/JupiterSwapper/models/RoutePlanStep.ts delete mode 100644 packages/swapper/src/swappers/JupiterSwapper/models/SwapInfo.ts delete mode 100644 packages/swapper/src/swappers/JupiterSwapper/models/SwapInstructionsResponse.ts delete mode 100644 packages/swapper/src/swappers/JupiterSwapper/models/SwapMode.ts diff --git a/package.json b/package.json index 0e4d9e0b56e..5e153bad19b 100644 --- a/package.json +++ b/package.json @@ -81,6 +81,7 @@ "@formatjs/intl-numberformat": "^8.10.3", "@formatjs/intl-pluralrules": "^5.2.14", "@json-rpc-tools/utils": "^1.7.6", + "@jup-ag/api": "^6.0.30", "@keepkey/hdwallet-keepkey-rest": "1.40.42", "@keepkey/keepkey-sdk": "0.2.57", "@ledgerhq/hw-transport-webusb": "^6.29.2", diff --git a/packages/swapper/src/constants.ts b/packages/swapper/src/constants.ts index 7332700f2eb..bb6999ee60f 100644 --- a/packages/swapper/src/constants.ts +++ b/packages/swapper/src/constants.ts @@ -105,7 +105,7 @@ const DEFAULT_LIFI_SLIPPAGE_DECIMAL_PERCENTAGE = '0.005' // .5% const DEFAULT_THOR_SLIPPAGE_DECIMAL_PERCENTAGE = '0.01' // 1% const DEFAULT_ARBITRUM_BRIDGE_SLIPPAGE_DECIMAL_PERCENTAGE = '0' // no slippage for Arbitrum Bridge, so no slippage tolerance const DEFAULT_CHAINFLIP_SLIPPAGE_DECIMAL_PERCENTAGE = '0.02' // 2% -const DEFAULT_JUPITER_SLIPPAGE_DECIMAL_PERCENTAGE = '0.01' // .5% +const DEFAULT_JUPITER_SLIPPAGE_DECIMAL_PERCENTAGE = '0.01' // 1% export const getDefaultSlippageDecimalPercentageForSwapper = ( swapperName?: SwapperName, diff --git a/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts b/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts index 0facaa8321b..f497007b6d0 100644 --- a/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts +++ b/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts @@ -38,10 +38,9 @@ import { isExecutableTradeStep, makeSwapErrorRight, } from '../../utils' -import type { Instruction } from './models/Instruction' -import type { QuoteResponse } from './models/QuoteResponse' -import { JUPITER_COMPUTE_UNIT_MARGIN_PERCENT, SOLANA_RANDOM_ADDRESS } from './utils/constants' +import { JUPITER_COMPUTE_UNIT_MARGIN_MULTIPLIER, SOLANA_RANDOM_ADDRESS } from './utils/constants' import { getJupiterPrice, getJupiterSwapInstructions, isSupportedChainId } from './utils/helpers' +import { Instruction, QuoteResponse } from '@jup-ag/api' const tradeQuoteMetadata: Map = new Map() @@ -83,6 +82,15 @@ export const jupiterApi: SwapperApi = { }), ) } + + if (buyAsset.assetId === wrappedSolAssetId || sellAsset.assetId === wrappedSolAssetId) { + return Err( + makeSwapErrorRight({ + message: `Unsupported trade pair`, + code: TradeQuoteError.UnsupportedTradePair, + }), + ) + } const maybePriceResponse = await getJupiterPrice({ apiUrl: jupiterUrl, @@ -342,7 +350,7 @@ export const jupiterApi: SwapperApi = { txFee: feeData.fast.txFee, chainSpecific: { computeUnits: bnOrZero(feeData.fast.chainSpecific.computeUnits) - .times(JUPITER_COMPUTE_UNIT_MARGIN_PERCENT) + .times(JUPITER_COMPUTE_UNIT_MARGIN_MULTIPLIER) .toFixed(0), priorityFee: feeData.fast.chainSpecific.priorityFee, }, diff --git a/packages/swapper/src/swappers/JupiterSwapper/models/AccountMeta.ts b/packages/swapper/src/swappers/JupiterSwapper/models/AccountMeta.ts deleted file mode 100644 index 7e485cf0429..00000000000 --- a/packages/swapper/src/swappers/JupiterSwapper/models/AccountMeta.ts +++ /dev/null @@ -1,84 +0,0 @@ -// @ts-nocheck -/* tslint:disable */ -/* eslint-disable */ -/** - * Jupiter API v6 - * The core of [jup.ag](https://jup.ag). Easily get a quote and swap through Jupiter API. ### Rate Limit We update our rate limit from time to time depending on the load of our servers. We recommend running your own instance of the API if you want to have high rate limit, here to learn how to run the [self-hosted API](https://station.jup.ag/docs/apis/self-hosted). ### API Wrapper - Typescript [@jup-ag/api](https://github.com/jup-ag/jupiter-quote-api-node) ### Data types - Public keys are base58 encoded strings - raw data such as Vec are base64 encoded strings - * - * The version of the OpenAPI document: 6.0.0 - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - -import { exists, mapValues } from '../runtime'; -/** - * - * @export - * @interface AccountMeta - */ -export interface AccountMeta { - /** - * - * @type {string} - * @memberof AccountMeta - */ - pubkey: string; - /** - * - * @type {boolean} - * @memberof AccountMeta - */ - isSigner: boolean; - /** - * - * @type {boolean} - * @memberof AccountMeta - */ - isWritable: boolean; -} - -/** - * Check if a given object implements the AccountMeta interface. - */ -export function instanceOfAccountMeta(value: object): boolean { - let isInstance = true; - isInstance = isInstance && "pubkey" in value; - isInstance = isInstance && "isSigner" in value; - isInstance = isInstance && "isWritable" in value; - - return isInstance; -} - -export function AccountMetaFromJSON(json: any): AccountMeta { - return AccountMetaFromJSONTyped(json, false); -} - -export function AccountMetaFromJSONTyped(json: any, ignoreDiscriminator: boolean): AccountMeta { - if ((json === undefined) || (json === null)) { - return json; - } - return { - - 'pubkey': json['pubkey'], - 'isSigner': json['isSigner'], - 'isWritable': json['isWritable'], - }; -} - -export function AccountMetaToJSON(value?: AccountMeta | null): any { - if (value === undefined) { - return undefined; - } - if (value === null) { - return null; - } - return { - - 'pubkey': value.pubkey, - 'isSigner': value.isSigner, - 'isWritable': value.isWritable, - }; -} diff --git a/packages/swapper/src/swappers/JupiterSwapper/models/Instruction.ts b/packages/swapper/src/swappers/JupiterSwapper/models/Instruction.ts deleted file mode 100644 index e1004f3e604..00000000000 --- a/packages/swapper/src/swappers/JupiterSwapper/models/Instruction.ts +++ /dev/null @@ -1,91 +0,0 @@ -// @ts-nocheck -/* tslint:disable */ -/* eslint-disable */ -/** - * Jupiter API v6 - * The core of [jup.ag](https://jup.ag). Easily get a quote and swap through Jupiter API. ### Rate Limit We update our rate limit from time to time depending on the load of our servers. We recommend running your own instance of the API if you want to have high rate limit, here to learn how to run the [self-hosted API](https://station.jup.ag/docs/apis/self-hosted). ### API Wrapper - Typescript [@jup-ag/api](https://github.com/jup-ag/jupiter-quote-api-node) ### Data types - Public keys are base58 encoded strings - raw data such as Vec are base64 encoded strings - * - * The version of the OpenAPI document: 6.0.0 - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - -import { exists, mapValues } from '../runtime'; -import type { AccountMeta } from './AccountMeta'; -import { - AccountMetaFromJSON, - AccountMetaFromJSONTyped, - AccountMetaToJSON, -} from './AccountMeta'; - -/** - * - * @export - * @interface Instruction - */ -export interface Instruction { - /** - * - * @type {string} - * @memberof Instruction - */ - programId: string; - /** - * - * @type {Array} - * @memberof Instruction - */ - accounts: Array; - /** - * - * @type {string} - * @memberof Instruction - */ - data: string; -} - -/** - * Check if a given object implements the Instruction interface. - */ -export function instanceOfInstruction(value: object): boolean { - let isInstance = true; - isInstance = isInstance && "programId" in value; - isInstance = isInstance && "accounts" in value; - isInstance = isInstance && "data" in value; - - return isInstance; -} - -export function InstructionFromJSON(json: any): Instruction { - return InstructionFromJSONTyped(json, false); -} - -export function InstructionFromJSONTyped(json: any, ignoreDiscriminator: boolean): Instruction { - if ((json === undefined) || (json === null)) { - return json; - } - return { - - 'programId': json['programId'], - 'accounts': ((json['accounts'] as Array).map(AccountMetaFromJSON)), - 'data': json['data'], - }; -} - -export function InstructionToJSON(value?: Instruction | null): any { - if (value === undefined) { - return undefined; - } - if (value === null) { - return null; - } - return { - - 'programId': value.programId, - 'accounts': ((value.accounts as Array).map(AccountMetaToJSON)), - 'data': value.data, - }; -} diff --git a/packages/swapper/src/swappers/JupiterSwapper/models/PlatformFee.ts b/packages/swapper/src/swappers/JupiterSwapper/models/PlatformFee.ts deleted file mode 100644 index 7b318eed167..00000000000 --- a/packages/swapper/src/swappers/JupiterSwapper/models/PlatformFee.ts +++ /dev/null @@ -1,73 +0,0 @@ -// @ts-nocheck -/* tslint:disable */ -/* eslint-disable */ -/** - * Jupiter API v6 - * The core of [jup.ag](https://jup.ag). Easily get a quote and swap through Jupiter API. ### Rate Limit We update our rate limit from time to time depending on the load of our servers. We recommend running your own instance of the API if you want to have high rate limit, here to learn how to run the [self-hosted API](https://station.jup.ag/docs/apis/self-hosted). ### API Wrapper - Typescript [@jup-ag/api](https://github.com/jup-ag/jupiter-quote-api-node) ### Data types - Public keys are base58 encoded strings - raw data such as Vec are base64 encoded strings - * - * The version of the OpenAPI document: 6.0.0 - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - -import { exists, mapValues } from '../runtime'; -/** - * - * @export - * @interface PlatformFee - */ -export interface PlatformFee { - /** - * - * @type {string} - * @memberof PlatformFee - */ - amount?: string; - /** - * - * @type {number} - * @memberof PlatformFee - */ - feeBps?: number; -} - -/** - * Check if a given object implements the PlatformFee interface. - */ -export function instanceOfPlatformFee(value: object): boolean { - let isInstance = true; - - return isInstance; -} - -export function PlatformFeeFromJSON(json: any): PlatformFee { - return PlatformFeeFromJSONTyped(json, false); -} - -export function PlatformFeeFromJSONTyped(json: any, ignoreDiscriminator: boolean): PlatformFee { - if ((json === undefined) || (json === null)) { - return json; - } - return { - - 'amount': !exists(json, 'amount') ? undefined : json['amount'], - 'feeBps': !exists(json, 'feeBps') ? undefined : json['feeBps'], - }; -} - -export function PlatformFeeToJSON(value?: PlatformFee | null): any { - if (value === undefined) { - return undefined; - } - if (value === null) { - return null; - } - return { - - 'amount': value.amount, - 'feeBps': value.feeBps, - }; -} diff --git a/packages/swapper/src/swappers/JupiterSwapper/models/QuoteResponse.ts b/packages/swapper/src/swappers/JupiterSwapper/models/QuoteResponse.ts deleted file mode 100644 index 92fec184a40..00000000000 --- a/packages/swapper/src/swappers/JupiterSwapper/models/QuoteResponse.ts +++ /dev/null @@ -1,189 +0,0 @@ -// @ts-nocheck -/* tslint:disable */ -/* eslint-disable */ -/** - * Jupiter API v6 - * The core of [jup.ag](https://jup.ag). Easily get a quote and swap through Jupiter API. ### Rate Limit We update our rate limit from time to time depending on the load of our servers. We recommend running your own instance of the API if you want to have high rate limit, here to learn how to run the [self-hosted API](https://station.jup.ag/docs/apis/self-hosted). ### API Wrapper - Typescript [@jup-ag/api](https://github.com/jup-ag/jupiter-quote-api-node) ### Data types - Public keys are base58 encoded strings - raw data such as Vec are base64 encoded strings - * - * The version of the OpenAPI document: 6.0.0 - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - -import { exists, mapValues } from '../runtime'; -import type { PlatformFee } from './PlatformFee'; -import { - PlatformFeeFromJSON, - PlatformFeeFromJSONTyped, - PlatformFeeToJSON, -} from './PlatformFee'; -import type { RoutePlanStep } from './RoutePlanStep.ts'; -import { - RoutePlanStepFromJSON, - RoutePlanStepFromJSONTyped, - RoutePlanStepToJSON, -} from './RoutePlanStep.ts'; -import type { SwapMode } from './SwapMode'; -import { - SwapModeFromJSON, - SwapModeFromJSONTyped, - SwapModeToJSON, -} from './SwapMode'; - -/** - * - * @export - * @interface QuoteResponse - */ -export interface QuoteResponse { - /** - * - * @type {string} - * @memberof QuoteResponse - */ - inputMint: string; - /** - * - * @type {string} - * @memberof QuoteResponse - */ - inAmount: string; - /** - * - * @type {string} - * @memberof QuoteResponse - */ - outputMint: string; - /** - * - * @type {string} - * @memberof QuoteResponse - */ - outAmount: string; - /** - * - * @type {string} - * @memberof QuoteResponse - */ - otherAmountThreshold: string; - /** - * - * @type {SwapMode} - * @memberof QuoteResponse - */ - swapMode: SwapMode; - /** - * - * @type {number} - * @memberof QuoteResponse - */ - slippageBps: number; - /** - * - * @type {number} - * @memberof QuoteResponse - */ - computedAutoSlippage?: number; - /** - * - * @type {PlatformFee} - * @memberof QuoteResponse - */ - platformFee?: PlatformFee; - /** - * - * @type {string} - * @memberof QuoteResponse - */ - priceImpactPct: string; - /** - * - * @type {Array} - * @memberof QuoteResponse - */ - routePlan: Array; - /** - * - * @type {number} - * @memberof QuoteResponse - */ - contextSlot?: number; - /** - * - * @type {number} - * @memberof QuoteResponse - */ - timeTaken?: number; -} - -/** - * Check if a given object implements the QuoteResponse interface. - */ -export function instanceOfQuoteResponse(value: object): boolean { - let isInstance = true; - isInstance = isInstance && "inputMint" in value; - isInstance = isInstance && "inAmount" in value; - isInstance = isInstance && "outputMint" in value; - isInstance = isInstance && "outAmount" in value; - isInstance = isInstance && "otherAmountThreshold" in value; - isInstance = isInstance && "swapMode" in value; - isInstance = isInstance && "slippageBps" in value; - isInstance = isInstance && "priceImpactPct" in value; - isInstance = isInstance && "routePlan" in value; - - return isInstance; -} - -export function QuoteResponseFromJSON(json: any): QuoteResponse { - return QuoteResponseFromJSONTyped(json, false); -} - -export function QuoteResponseFromJSONTyped(json: any, ignoreDiscriminator: boolean): QuoteResponse { - if ((json === undefined) || (json === null)) { - return json; - } - return { - - 'inputMint': json['inputMint'], - 'inAmount': json['inAmount'], - 'outputMint': json['outputMint'], - 'outAmount': json['outAmount'], - 'otherAmountThreshold': json['otherAmountThreshold'], - 'swapMode': SwapModeFromJSON(json['swapMode']), - 'slippageBps': json['slippageBps'], - 'computedAutoSlippage': !exists(json, 'computedAutoSlippage') ? undefined : json['computedAutoSlippage'], - 'platformFee': !exists(json, 'platformFee') ? undefined : PlatformFeeFromJSON(json['platformFee']), - 'priceImpactPct': json['priceImpactPct'], - 'routePlan': ((json['routePlan'] as Array).map(RoutePlanStepFromJSON)), - 'contextSlot': !exists(json, 'contextSlot') ? undefined : json['contextSlot'], - 'timeTaken': !exists(json, 'timeTaken') ? undefined : json['timeTaken'], - }; -} - -export function QuoteResponseToJSON(value?: QuoteResponse | null): any { - if (value === undefined) { - return undefined; - } - if (value === null) { - return null; - } - return { - - 'inputMint': value.inputMint, - 'inAmount': value.inAmount, - 'outputMint': value.outputMint, - 'outAmount': value.outAmount, - 'otherAmountThreshold': value.otherAmountThreshold, - 'swapMode': SwapModeToJSON(value.swapMode), - 'slippageBps': value.slippageBps, - 'computedAutoSlippage': value.computedAutoSlippage, - 'platformFee': PlatformFeeToJSON(value.platformFee), - 'priceImpactPct': value.priceImpactPct, - 'routePlan': ((value.routePlan as Array).map(RoutePlanStepToJSON)), - 'contextSlot': value.contextSlot, - 'timeTaken': value.timeTaken, - }; -} diff --git a/packages/swapper/src/swappers/JupiterSwapper/models/RoutePlanStep.ts b/packages/swapper/src/swappers/JupiterSwapper/models/RoutePlanStep.ts deleted file mode 100644 index 39ae6a22c5c..00000000000 --- a/packages/swapper/src/swappers/JupiterSwapper/models/RoutePlanStep.ts +++ /dev/null @@ -1,82 +0,0 @@ -// @ts-nocheck -/* tslint:disable */ -/* eslint-disable */ -/** - * Jupiter API v6 - * The core of [jup.ag](https://jup.ag). Easily get a quote and swap through Jupiter API. ### Rate Limit We update our rate limit from time to time depending on the load of our servers. We recommend running your own instance of the API if you want to have high rate limit, here to learn how to run the [self-hosted API](https://station.jup.ag/docs/apis/self-hosted). ### API Wrapper - Typescript [@jup-ag/api](https://github.com/jup-ag/jupiter-quote-api-node) ### Data types - Public keys are base58 encoded strings - raw data such as Vec are base64 encoded strings - * - * The version of the OpenAPI document: 6.0.0 - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - -import { exists, mapValues } from '../runtime'; -import type { SwapInfo } from './SwapInfo'; -import { - SwapInfoFromJSON, - SwapInfoFromJSONTyped, - SwapInfoToJSON, -} from './SwapInfo'; - -/** - * - * @export - * @interface RoutePlanStep - */ -export interface RoutePlanStep { - /** - * - * @type {SwapInfo} - * @memberof RoutePlanStep - */ - swapInfo: SwapInfo; - /** - * - * @type {number} - * @memberof RoutePlanStep - */ - percent: number; -} - -/** - * Check if a given object implements the RoutePlanStep interface. - */ -export function instanceOfRoutePlanStep(value: object): boolean { - let isInstance = true; - isInstance = isInstance && "swapInfo" in value; - isInstance = isInstance && "percent" in value; - - return isInstance; -} - -export function RoutePlanStepFromJSON(json: any): RoutePlanStep { - return RoutePlanStepFromJSONTyped(json, false); -} - -export function RoutePlanStepFromJSONTyped(json: any, ignoreDiscriminator: boolean): RoutePlanStep { - if ((json === undefined) || (json === null)) { - return json; - } - return { - - 'swapInfo': SwapInfoFromJSON(json['swapInfo']), - 'percent': json['percent'], - }; -} - -export function RoutePlanStepToJSON(value?: RoutePlanStep | null): any { - if (value === undefined) { - return undefined; - } - if (value === null) { - return null; - } - return { - - 'swapInfo': SwapInfoToJSON(value.swapInfo), - 'percent': value.percent, - }; -} diff --git a/packages/swapper/src/swappers/JupiterSwapper/models/SwapInfo.ts b/packages/swapper/src/swappers/JupiterSwapper/models/SwapInfo.ts deleted file mode 100644 index 4ee72ea7470..00000000000 --- a/packages/swapper/src/swappers/JupiterSwapper/models/SwapInfo.ts +++ /dev/null @@ -1,128 +0,0 @@ -// @ts-nocheck -/* tslint:disable */ -/* eslint-disable */ -/** - * Jupiter API v6 - * The core of [jup.ag](https://jup.ag). Easily get a quote and swap through Jupiter API. ### Rate Limit We update our rate limit from time to time depending on the load of our servers. We recommend running your own instance of the API if you want to have high rate limit, here to learn how to run the [self-hosted API](https://station.jup.ag/docs/apis/self-hosted). ### API Wrapper - Typescript [@jup-ag/api](https://github.com/jup-ag/jupiter-quote-api-node) ### Data types - Public keys are base58 encoded strings - raw data such as Vec are base64 encoded strings - * - * The version of the OpenAPI document: 6.0.0 - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - -import { exists, mapValues } from '../runtime'; -/** - * - * @export - * @interface SwapInfo - */ -export interface SwapInfo { - /** - * - * @type {string} - * @memberof SwapInfo - */ - ammKey: string; - /** - * - * @type {string} - * @memberof SwapInfo - */ - label?: string; - /** - * - * @type {string} - * @memberof SwapInfo - */ - inputMint: string; - /** - * - * @type {string} - * @memberof SwapInfo - */ - outputMint: string; - /** - * - * @type {string} - * @memberof SwapInfo - */ - inAmount: string; - /** - * - * @type {string} - * @memberof SwapInfo - */ - outAmount: string; - /** - * - * @type {string} - * @memberof SwapInfo - */ - feeAmount: string; - /** - * - * @type {string} - * @memberof SwapInfo - */ - feeMint: string; -} - -/** - * Check if a given object implements the SwapInfo interface. - */ -export function instanceOfSwapInfo(value: object): boolean { - let isInstance = true; - isInstance = isInstance && "ammKey" in value; - isInstance = isInstance && "inputMint" in value; - isInstance = isInstance && "outputMint" in value; - isInstance = isInstance && "inAmount" in value; - isInstance = isInstance && "outAmount" in value; - isInstance = isInstance && "feeAmount" in value; - isInstance = isInstance && "feeMint" in value; - - return isInstance; -} - -export function SwapInfoFromJSON(json: any): SwapInfo { - return SwapInfoFromJSONTyped(json, false); -} - -export function SwapInfoFromJSONTyped(json: any, ignoreDiscriminator: boolean): SwapInfo { - if ((json === undefined) || (json === null)) { - return json; - } - return { - - 'ammKey': json['ammKey'], - 'label': !exists(json, 'label') ? undefined : json['label'], - 'inputMint': json['inputMint'], - 'outputMint': json['outputMint'], - 'inAmount': json['inAmount'], - 'outAmount': json['outAmount'], - 'feeAmount': json['feeAmount'], - 'feeMint': json['feeMint'], - }; -} - -export function SwapInfoToJSON(value?: SwapInfo | null): any { - if (value === undefined) { - return undefined; - } - if (value === null) { - return null; - } - return { - - 'ammKey': value.ammKey, - 'label': value.label, - 'inputMint': value.inputMint, - 'outputMint': value.outputMint, - 'inAmount': value.inAmount, - 'outAmount': value.outAmount, - 'feeAmount': value.feeAmount, - 'feeMint': value.feeMint, - }; -} diff --git a/packages/swapper/src/swappers/JupiterSwapper/models/SwapInstructionsResponse.ts b/packages/swapper/src/swappers/JupiterSwapper/models/SwapInstructionsResponse.ts deleted file mode 100644 index e844dff146b..00000000000 --- a/packages/swapper/src/swappers/JupiterSwapper/models/SwapInstructionsResponse.ts +++ /dev/null @@ -1,116 +0,0 @@ -// @ts-nocheck -/* tslint:disable */ -/* eslint-disable */ -/** - * Jupiter API v6 - * The core of [jup.ag](https://jup.ag). Easily get a quote and swap through Jupiter API. ### Rate Limit We update our rate limit from time to time depending on the load of our servers. We recommend running your own instance of the API if you want to have high rate limit, here to learn how to run the [self-hosted API](https://station.jup.ag/docs/apis/self-hosted). ### API Wrapper - Typescript [@jup-ag/api](https://github.com/jup-ag/jupiter-quote-api-node) ### Data types - Public keys are base58 encoded strings - raw data such as Vec are base64 encoded strings - * - * The version of the OpenAPI document: 6.0.0 - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - -import { exists, mapValues } from '../runtime'; -import type { Instruction } from './Instruction'; -import { - InstructionFromJSON, - InstructionFromJSONTyped, - InstructionToJSON, -} from './Instruction'; - -/** - * - * @export - * @interface SwapInstructionsResponse - */ -export interface SwapInstructionsResponse { - /** - * - * @type {Instruction} - * @memberof SwapInstructionsResponse - */ - tokenLedgerInstruction?: Instruction; - /** - * The necessary instructions to setup the compute budget. - * @type {Array} - * @memberof SwapInstructionsResponse - */ - computeBudgetInstructions: Array; - /** - * Setup missing ATA for the users. - * @type {Array} - * @memberof SwapInstructionsResponse - */ - setupInstructions: Array; - /** - * - * @type {Instruction} - * @memberof SwapInstructionsResponse - */ - swapInstruction: Instruction; - /** - * - * @type {Instruction} - * @memberof SwapInstructionsResponse - */ - cleanupInstruction?: Instruction; - /** - * The lookup table addresses that you can use if you are using versioned transaction. - * @type {Array} - * @memberof SwapInstructionsResponse - */ - addressLookupTableAddresses: Array; -} - -/** - * Check if a given object implements the SwapInstructionsResponse interface. - */ -export function instanceOfSwapInstructionsResponse(value: object): boolean { - let isInstance = true; - isInstance = isInstance && "computeBudgetInstructions" in value; - isInstance = isInstance && "setupInstructions" in value; - isInstance = isInstance && "swapInstruction" in value; - isInstance = isInstance && "addressLookupTableAddresses" in value; - - return isInstance; -} - -export function SwapInstructionsResponseFromJSON(json: any): SwapInstructionsResponse { - return SwapInstructionsResponseFromJSONTyped(json, false); -} - -export function SwapInstructionsResponseFromJSONTyped(json: any, ignoreDiscriminator: boolean): SwapInstructionsResponse { - if ((json === undefined) || (json === null)) { - return json; - } - return { - - 'tokenLedgerInstruction': !exists(json, 'tokenLedgerInstruction') ? undefined : InstructionFromJSON(json['tokenLedgerInstruction']), - 'computeBudgetInstructions': ((json['computeBudgetInstructions'] as Array).map(InstructionFromJSON)), - 'setupInstructions': ((json['setupInstructions'] as Array).map(InstructionFromJSON)), - 'swapInstruction': InstructionFromJSON(json['swapInstruction']), - 'cleanupInstruction': !exists(json, 'cleanupInstruction') ? undefined : InstructionFromJSON(json['cleanupInstruction']), - 'addressLookupTableAddresses': json['addressLookupTableAddresses'], - }; -} - -export function SwapInstructionsResponseToJSON(value?: SwapInstructionsResponse | null): any { - if (value === undefined) { - return undefined; - } - if (value === null) { - return null; - } - return { - - 'tokenLedgerInstruction': InstructionToJSON(value.tokenLedgerInstruction), - 'computeBudgetInstructions': ((value.computeBudgetInstructions as Array).map(InstructionToJSON)), - 'setupInstructions': ((value.setupInstructions as Array).map(InstructionToJSON)), - 'swapInstruction': InstructionToJSON(value.swapInstruction), - 'cleanupInstruction': InstructionToJSON(value.cleanupInstruction), - 'addressLookupTableAddresses': value.addressLookupTableAddresses, - }; -} diff --git a/packages/swapper/src/swappers/JupiterSwapper/models/SwapMode.ts b/packages/swapper/src/swappers/JupiterSwapper/models/SwapMode.ts deleted file mode 100644 index 63b5e3df433..00000000000 --- a/packages/swapper/src/swappers/JupiterSwapper/models/SwapMode.ts +++ /dev/null @@ -1,38 +0,0 @@ -// @ts-nocheck -/* tslint:disable */ -/* eslint-disable */ -/** - * Jupiter API v6 - * The core of [jup.ag](https://jup.ag). Easily get a quote and swap through Jupiter API. ### Rate Limit We update our rate limit from time to time depending on the load of our servers. We recommend running your own instance of the API if you want to have high rate limit, here to learn how to run the [self-hosted API](https://station.jup.ag/docs/apis/self-hosted). ### API Wrapper - Typescript [@jup-ag/api](https://github.com/jup-ag/jupiter-quote-api-node) ### Data types - Public keys are base58 encoded strings - raw data such as Vec are base64 encoded strings - * - * The version of the OpenAPI document: 6.0.0 - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - - -/** - * - * @export - */ -export const SwapMode = { - ExactIn: 'ExactIn', - ExactOut: 'ExactOut' -} as const; -export type SwapMode = typeof SwapMode[keyof typeof SwapMode]; - - -export function SwapModeFromJSON(json: any): SwapMode { - return SwapModeFromJSONTyped(json, false); -} - -export function SwapModeFromJSONTyped(json: any, ignoreDiscriminator: boolean): SwapMode { - return json as SwapMode; -} - -export function SwapModeToJSON(value?: SwapMode | null): any { - return value as any; -} diff --git a/packages/swapper/src/swappers/JupiterSwapper/utils/constants.ts b/packages/swapper/src/swappers/JupiterSwapper/utils/constants.ts index 99803b905ed..a196d3a652c 100644 --- a/packages/swapper/src/swappers/JupiterSwapper/utils/constants.ts +++ b/packages/swapper/src/swappers/JupiterSwapper/utils/constants.ts @@ -13,4 +13,4 @@ export const JUPITER_SUPPORTED_CHAIN_IDS: SupportedChainIds = { export const SOLANA_RANDOM_ADDRESS = '2zHKF6tqam3tnNFPK2E9nBDkV7GMXnvdJautmzqQdn8A' // Jupiter use 40% as a compute unit margin while calculating them, some TX reverts without this -export const JUPITER_COMPUTE_UNIT_MARGIN_PERCENT = 1.4 +export const JUPITER_COMPUTE_UNIT_MARGIN_MULTIPLIER = 1.4 diff --git a/packages/swapper/src/swappers/JupiterSwapper/utils/helpers.ts b/packages/swapper/src/swappers/JupiterSwapper/utils/helpers.ts index b8ee46e53a4..a038197cce5 100644 --- a/packages/swapper/src/swappers/JupiterSwapper/utils/helpers.ts +++ b/packages/swapper/src/swappers/JupiterSwapper/utils/helpers.ts @@ -4,10 +4,9 @@ import type { Result } from '@sniptt/monads' import type { AxiosResponse } from 'axios' import type { SwapErrorRight } from '../../../types' -import type { QuoteResponse } from '../models/QuoteResponse' -import type { SwapInstructionsResponse } from '../models/SwapInstructionsResponse' import { jupiterSupportedChainIds } from './constants' import { jupiterService } from './jupiterService' +import { QuoteResponse, SwapInstructionsResponse } from '@jup-ag/api' export const isSupportedChainId = (chainId: ChainId): chainId is KnownChainIds.SolanaMainnet => { return jupiterSupportedChainIds.includes(chainId) diff --git a/packages/swapper/src/types.ts b/packages/swapper/src/types.ts index 4997c299b58..3a7a9d5d2bc 100644 --- a/packages/swapper/src/types.ts +++ b/packages/swapper/src/types.ts @@ -27,8 +27,8 @@ import type { InterpolationOptions } from 'node-polyglot' import type { Address } from 'viem' import type { CowMessageToSign, CowSwapQuoteResponse } from './swappers/CowSwapper/types' -import type { QuoteResponse } from './swappers/JupiterSwapper/models/QuoteResponse' import type { makeSwapperAxiosServiceMonadic } from './utils' +import { QuoteResponse } from '@jup-ag/api' // TODO: Rename all properties in this type to be camel case and not react specific export type SwapperConfig = { diff --git a/yarn.lock b/yarn.lock index 8b38efd17f3..3852ad54d47 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7930,6 +7930,13 @@ __metadata: languageName: node linkType: hard +"@jup-ag/api@npm:^6.0.30": + version: 6.0.30 + resolution: "@jup-ag/api@npm:6.0.30" + checksum: a2a3fb30b1837ef2b215d54df72a7e1567be0c30a9177fe4042ac5078e1fa2106b1005098fb04d7e8b9543fc8be136d7d6496945901b724481e9982b68dfb79c + languageName: node + linkType: hard + "@keepkey/device-protocol@npm:^7.12.2": version: 7.12.2 resolution: "@keepkey/device-protocol@npm:7.12.2" @@ -11741,6 +11748,7 @@ __metadata: "@formatjs/intl-numberformat": ^8.10.3 "@formatjs/intl-pluralrules": ^5.2.14 "@json-rpc-tools/utils": ^1.7.6 + "@jup-ag/api": ^6.0.30 "@keepkey/hdwallet-keepkey-rest": 1.40.42 "@keepkey/keepkey-sdk": 0.2.57 "@keplr-wallet/types": ^0.12.21 From 578080067d966c0b382860fda2c36afef6621d92 Mon Sep 17 00:00:00 2001 From: NeOMakinG <14963751+NeOMakinG@users.noreply.github.com> Date: Wed, 27 Nov 2024 14:16:02 +0100 Subject: [PATCH 124/127] fix: refetch prices at quote time --- .../src/swappers/JupiterSwapper/endpoints.ts | 28 ++++++++++++++----- .../swappers/JupiterSwapper/utils/helpers.ts | 5 ++-- packages/swapper/src/types.ts | 2 +- 3 files changed, 25 insertions(+), 10 deletions(-) diff --git a/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts b/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts index f497007b6d0..da3de65f829 100644 --- a/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts +++ b/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts @@ -1,3 +1,4 @@ +import type { Instruction, QuoteResponse } from '@jup-ag/api' import type { AssetId } from '@shapeshiftoss/caip' import { ASSET_NAMESPACE, @@ -14,7 +15,8 @@ import type { KnownChainIds } from '@shapeshiftoss/types' import { bnOrZero, convertDecimalPercentageToBasisPoints } from '@shapeshiftoss/utils' import type { Result } from '@sniptt/monads' import { Err, Ok } from '@sniptt/monads' -import { PublicKey, type TransactionInstruction } from '@solana/web3.js' +import type { TransactionInstruction } from '@solana/web3.js' +import { PublicKey } from '@solana/web3.js' import type { AxiosError } from 'axios' import { v4 as uuid } from 'uuid' @@ -40,7 +42,6 @@ import { } from '../../utils' import { JUPITER_COMPUTE_UNIT_MARGIN_MULTIPLIER, SOLANA_RANDOM_ADDRESS } from './utils/constants' import { getJupiterPrice, getJupiterSwapInstructions, isSupportedChainId } from './utils/helpers' -import { Instruction, QuoteResponse } from '@jup-ag/api' const tradeQuoteMetadata: Map = new Map() @@ -82,7 +83,7 @@ export const jupiterApi: SwapperApi = { }), ) } - + if (buyAsset.assetId === wrappedSolAssetId || sellAsset.assetId === wrappedSolAssetId) { return Err( makeSwapErrorRight({ @@ -221,6 +222,7 @@ export const jupiterApi: SwapperApi = { receiveAddress, accountNumber, sendAddress, + sellAmountIncludingProtocolFeesCryptoBaseUnit: sellAmount, slippageTolerancePercentageDecimal, } = input @@ -266,17 +268,29 @@ export const jupiterApi: SwapperApi = { ) } - const quoteResponse = tradeQuoteMetadata.get('rate') + const maybePriceResponse = await getJupiterPrice({ + apiUrl: jupiterUrl, + sourceAsset: sellAsset.assetId === solAssetId ? wrappedSolAssetId : sellAsset.assetId, + destinationAsset: buyAsset.assetId === solAssetId ? wrappedSolAssetId : buyAsset.assetId, + commissionBps: affiliateBps, + amount: sellAmount, + slippageBps: convertDecimalPercentageToBasisPoints( + slippageTolerancePercentageDecimal ?? + getDefaultSlippageDecimalPercentageForSwapper(SwapperName.Jupiter), + ).toFixed(), + }) - if (!quoteResponse) { + if (maybePriceResponse.isErr()) { return Err( makeSwapErrorRight({ - message: `quote not found`, - code: TradeQuoteError.UnknownError, + message: 'Quote request failed', + code: TradeQuoteError.NoRouteFound, }), ) } + const { data: quoteResponse } = maybePriceResponse.unwrap() + const contractAddress = buyAsset.assetId === solAssetId ? undefined : fromAssetId(buyAsset.assetId).assetReference diff --git a/packages/swapper/src/swappers/JupiterSwapper/utils/helpers.ts b/packages/swapper/src/swappers/JupiterSwapper/utils/helpers.ts index a038197cce5..b0442c4b74e 100644 --- a/packages/swapper/src/swappers/JupiterSwapper/utils/helpers.ts +++ b/packages/swapper/src/swappers/JupiterSwapper/utils/helpers.ts @@ -1,4 +1,6 @@ -import { type ChainId, fromAssetId } from '@shapeshiftoss/caip' +import type { QuoteResponse, SwapInstructionsResponse } from '@jup-ag/api' +import type { ChainId } from '@shapeshiftoss/caip' +import { fromAssetId } from '@shapeshiftoss/caip' import type { KnownChainIds } from '@shapeshiftoss/types' import type { Result } from '@sniptt/monads' import type { AxiosResponse } from 'axios' @@ -6,7 +8,6 @@ import type { AxiosResponse } from 'axios' import type { SwapErrorRight } from '../../../types' import { jupiterSupportedChainIds } from './constants' import { jupiterService } from './jupiterService' -import { QuoteResponse, SwapInstructionsResponse } from '@jup-ag/api' export const isSupportedChainId = (chainId: ChainId): chainId is KnownChainIds.SolanaMainnet => { return jupiterSupportedChainIds.includes(chainId) diff --git a/packages/swapper/src/types.ts b/packages/swapper/src/types.ts index c1251a4d110..83798114596 100644 --- a/packages/swapper/src/types.ts +++ b/packages/swapper/src/types.ts @@ -1,3 +1,4 @@ +import type { QuoteResponse } from '@jup-ag/api' import type { StdSignDoc } from '@keplr-wallet/types' import type { AccountId, AssetId, ChainId, Nominal } from '@shapeshiftoss/caip' import type { @@ -29,7 +30,6 @@ import type { Address } from 'viem' import type { CowMessageToSign } from './swappers/CowSwapper/types' import type { makeSwapperAxiosServiceMonadic } from './utils' -import { QuoteResponse } from '@jup-ag/api' // TODO: Rename all properties in this type to be camel case and not react specific export type SwapperConfig = { From 0157593402718f6446981b125f3ae0d5e144bcde Mon Sep 17 00:00:00 2001 From: NeOMakinG <14963751+NeOMakinG@users.noreply.github.com> Date: Wed, 27 Nov 2024 15:53:07 +0100 Subject: [PATCH 125/127] fix: remove metadata mapping --- packages/swapper/src/swappers/JupiterSwapper/endpoints.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts b/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts index da3de65f829..182d1ae6214 100644 --- a/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts +++ b/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts @@ -1,4 +1,4 @@ -import type { Instruction, QuoteResponse } from '@jup-ag/api' +import type { Instruction } from '@jup-ag/api' import type { AssetId } from '@shapeshiftoss/caip' import { ASSET_NAMESPACE, @@ -43,8 +43,6 @@ import { import { JUPITER_COMPUTE_UNIT_MARGIN_MULTIPLIER, SOLANA_RANDOM_ADDRESS } from './utils/constants' import { getJupiterPrice, getJupiterSwapInstructions, isSupportedChainId } from './utils/helpers' -const tradeQuoteMetadata: Map = new Map() - export const jupiterApi: SwapperApi = { getTradeRate: async ( input: GetTradeRateInput, @@ -116,8 +114,6 @@ export const jupiterApi: SwapperApi = { const { data: quoteResponse } = maybePriceResponse.unwrap() - tradeQuoteMetadata.set('rate', quoteResponse) - const getFeeData = async () => { const sellAdapter = deps.assertGetSolanaChainAdapter(sellAsset.chainId) const getFeeDataInput: GetFeeDataInput = { From 3f8c1d115f85fc8a3da7f290f1c2af0b2d3bb5fb Mon Sep 17 00:00:00 2001 From: NeOMakinG <14963751+NeOMakinG@users.noreply.github.com> Date: Wed, 27 Nov 2024 16:05:16 +0100 Subject: [PATCH 126/127] fix: split quote and rate --- .../src/swappers/JupiterSwapper/endpoints.ts | 451 +----------------- .../swapperApi/getTradeQuote.ts | 273 +++++++++++ .../JupiterSwapper/swapperApi/getTradeRate.ts | 193 ++++++++ 3 files changed, 474 insertions(+), 443 deletions(-) create mode 100644 packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeQuote.ts create mode 100644 packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeRate.ts diff --git a/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts b/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts index 182d1ae6214..70ad7d146d9 100644 --- a/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts +++ b/packages/swapper/src/swappers/JupiterSwapper/endpoints.ts @@ -1,451 +1,16 @@ -import type { Instruction } from '@jup-ag/api' -import type { AssetId } from '@shapeshiftoss/caip' -import { - ASSET_NAMESPACE, - CHAIN_NAMESPACE, - CHAIN_REFERENCE, - fromAssetId, - solAssetId, - toAssetId, - wrappedSolAssetId, -} from '@shapeshiftoss/caip' -import type { BuildSendApiTxInput, GetFeeDataInput } from '@shapeshiftoss/chain-adapters' +import type { BuildSendApiTxInput } from '@shapeshiftoss/chain-adapters' import type { SolanaSignTx } from '@shapeshiftoss/hdwallet-core' import type { KnownChainIds } from '@shapeshiftoss/types' -import { bnOrZero, convertDecimalPercentageToBasisPoints } from '@shapeshiftoss/utils' -import type { Result } from '@sniptt/monads' -import { Err, Ok } from '@sniptt/monads' -import type { TransactionInstruction } from '@solana/web3.js' -import { PublicKey } from '@solana/web3.js' -import type { AxiosError } from 'axios' -import { v4 as uuid } from 'uuid' -import { getDefaultSlippageDecimalPercentageForSwapper } from '../../constants' -import type { - CommonTradeQuoteInput, - GetTradeRateInput, - GetUnsignedSolanaTransactionArgs, - ProtocolFee, - SwapErrorRight, - SwapperApi, - SwapperDeps, - TradeQuote, - TradeRate, -} from '../../types' -import { isSolanaFeeData, SwapperName, TradeQuoteError } from '../../types' -import { - checkSolanaSwapStatus, - getRate, - isExecutableTradeQuote, - isExecutableTradeStep, - makeSwapErrorRight, -} from '../../utils' -import { JUPITER_COMPUTE_UNIT_MARGIN_MULTIPLIER, SOLANA_RANDOM_ADDRESS } from './utils/constants' -import { getJupiterPrice, getJupiterSwapInstructions, isSupportedChainId } from './utils/helpers' +import type { GetUnsignedSolanaTransactionArgs, SwapperApi } from '../../types' +import { isSolanaFeeData } from '../../types' +import { checkSolanaSwapStatus, isExecutableTradeQuote, isExecutableTradeStep } from '../../utils' +import { getTradeQuote } from './swapperApi/getTradeQuote' +import { getTradeRate } from './swapperApi/getTradeRate' export const jupiterApi: SwapperApi = { - getTradeRate: async ( - input: GetTradeRateInput, - deps: SwapperDeps, - ): Promise> => { - const { - sellAsset, - buyAsset, - sellAmountIncludingProtocolFeesCryptoBaseUnit: sellAmount, - affiliateBps, - receiveAddress, - accountNumber, - slippageTolerancePercentageDecimal, - } = input - - const { assetsById } = deps - - const jupiterUrl = deps.config.REACT_APP_JUPITER_API_URL - - if (!isSupportedChainId(sellAsset.chainId)) { - return Err( - makeSwapErrorRight({ - message: `unsupported chainId`, - code: TradeQuoteError.UnsupportedChain, - details: { chainId: sellAsset.chainId }, - }), - ) - } - - if (!isSupportedChainId(buyAsset.chainId)) { - return Err( - makeSwapErrorRight({ - message: `unsupported chainId`, - code: TradeQuoteError.UnsupportedChain, - details: { chainId: sellAsset.chainId }, - }), - ) - } - - if (buyAsset.assetId === wrappedSolAssetId || sellAsset.assetId === wrappedSolAssetId) { - return Err( - makeSwapErrorRight({ - message: `Unsupported trade pair`, - code: TradeQuoteError.UnsupportedTradePair, - }), - ) - } - - const maybePriceResponse = await getJupiterPrice({ - apiUrl: jupiterUrl, - sourceAsset: sellAsset.assetId === solAssetId ? wrappedSolAssetId : sellAsset.assetId, - destinationAsset: buyAsset.assetId === solAssetId ? wrappedSolAssetId : buyAsset.assetId, - commissionBps: affiliateBps, - amount: sellAmount, - slippageBps: convertDecimalPercentageToBasisPoints( - slippageTolerancePercentageDecimal ?? - getDefaultSlippageDecimalPercentageForSwapper(SwapperName.Jupiter), - ).toFixed(), - }) - - if (maybePriceResponse.isErr()) { - return Err( - makeSwapErrorRight({ - message: 'Quote request failed', - code: TradeQuoteError.NoRouteFound, - }), - ) - } - - const { data: quoteResponse } = maybePriceResponse.unwrap() - - const getFeeData = async () => { - const sellAdapter = deps.assertGetSolanaChainAdapter(sellAsset.chainId) - const getFeeDataInput: GetFeeDataInput = { - // used as a placeholder for the sake of loosely estimating fees - to: SOLANA_RANDOM_ADDRESS, - value: sellAmount, - chainSpecific: { - from: SOLANA_RANDOM_ADDRESS, - tokenId: - sellAsset.assetId === solAssetId - ? undefined - : fromAssetId(sellAsset.assetId).assetReference, - }, - } - const { fast } = await sellAdapter.getFeeData(getFeeDataInput) - return { networkFeeCryptoBaseUnit: fast.txFee } - } - - const protocolFees: Record = quoteResponse.routePlan.reduce( - (acc, route) => { - const feeAssetId = toAssetId({ - assetReference: route.swapInfo.feeMint, - assetNamespace: ASSET_NAMESPACE.splToken, - chainNamespace: CHAIN_NAMESPACE.Solana, - chainReference: CHAIN_REFERENCE.SolanaMainnet, - }) - const feeAsset = assetsById[feeAssetId] - - // If we can't find the feeAsset, we can't provide a protocol fee to display - // But these fees exists at protocol level, it's mostly to make TS happy as we should have the market data and assets - if (!feeAsset) return acc - - acc[feeAssetId] = { - requiresBalance: false, - amountCryptoBaseUnit: bnOrZero(route.swapInfo.feeAmount).toFixed(0), - asset: feeAsset, - } - - return acc - }, - {} as Record, - ) - - const getQuoteRate = (sellAmountCryptoBaseUnit: string, buyAmountCryptoBaseUnit: string) => { - return getRate({ - sellAmountCryptoBaseUnit, - buyAmountCryptoBaseUnit, - sellAsset, - buyAsset, - }) - } - - const rates: TradeRate[] = [] - - const feeData = await getFeeData() - - const rate = getQuoteRate(quoteResponse.inAmount, quoteResponse.outAmount) - - const tradeRate: TradeRate = { - id: uuid(), - rate, - receiveAddress, - potentialAffiliateBps: affiliateBps, - affiliateBps, - accountNumber, - slippageTolerancePercentageDecimal: - slippageTolerancePercentageDecimal ?? - getDefaultSlippageDecimalPercentageForSwapper(SwapperName.Jupiter), - steps: [ - { - buyAmountBeforeFeesCryptoBaseUnit: quoteResponse.outAmount, - buyAmountAfterFeesCryptoBaseUnit: quoteResponse.outAmount, - sellAmountIncludingProtocolFeesCryptoBaseUnit: quoteResponse.inAmount, - jupiterQuoteResponse: quoteResponse, - feeData: { - protocolFees, - ...feeData, - }, - rate, - source: SwapperName.Jupiter, - buyAsset, - sellAsset, - accountNumber, - allowanceContract: '0x0', - estimatedExecutionTimeMs: quoteResponse.timeTaken! * 1000, - }, - ], - } - - rates.push(tradeRate) - - return Ok(rates) - }, - getTradeQuote: async ( - input: CommonTradeQuoteInput, - deps: SwapperDeps, - ): Promise> => { - const { - sellAsset, - buyAsset, - affiliateBps, - receiveAddress, - accountNumber, - sendAddress, - sellAmountIncludingProtocolFeesCryptoBaseUnit: sellAmount, - slippageTolerancePercentageDecimal, - } = input - - const { assetsById } = deps - - const jupiterUrl = deps.config.REACT_APP_JUPITER_API_URL - - if (accountNumber === undefined) { - return Err( - makeSwapErrorRight({ - message: `accountNumber is required`, - code: TradeQuoteError.UnknownError, - }), - ) - } - - if (!isSupportedChainId(sellAsset.chainId)) { - return Err( - makeSwapErrorRight({ - message: `unsupported chainId`, - code: TradeQuoteError.UnsupportedChain, - details: { chainId: sellAsset.chainId }, - }), - ) - } - - if (!isSupportedChainId(buyAsset.chainId)) { - return Err( - makeSwapErrorRight({ - message: `unsupported chainId`, - code: TradeQuoteError.UnsupportedChain, - details: { chainId: sellAsset.chainId }, - }), - ) - } - - if (!sendAddress) { - return Err( - makeSwapErrorRight({ - message: `sendAddress is required`, - code: TradeQuoteError.UnknownError, - }), - ) - } - - const maybePriceResponse = await getJupiterPrice({ - apiUrl: jupiterUrl, - sourceAsset: sellAsset.assetId === solAssetId ? wrappedSolAssetId : sellAsset.assetId, - destinationAsset: buyAsset.assetId === solAssetId ? wrappedSolAssetId : buyAsset.assetId, - commissionBps: affiliateBps, - amount: sellAmount, - slippageBps: convertDecimalPercentageToBasisPoints( - slippageTolerancePercentageDecimal ?? - getDefaultSlippageDecimalPercentageForSwapper(SwapperName.Jupiter), - ).toFixed(), - }) - - if (maybePriceResponse.isErr()) { - return Err( - makeSwapErrorRight({ - message: 'Quote request failed', - code: TradeQuoteError.NoRouteFound, - }), - ) - } - - const { data: quoteResponse } = maybePriceResponse.unwrap() - - const contractAddress = - buyAsset.assetId === solAssetId ? undefined : fromAssetId(buyAsset.assetId).assetReference - - const adapter = deps.assertGetSolanaChainAdapter(sellAsset.chainId) - - const isCrossAccountTrade = receiveAddress ? receiveAddress !== sendAddress : false - - const { instruction: createTokenAccountInstruction, destinationTokenAccount } = - contractAddress && isCrossAccountTrade - ? await adapter.createAssociatedTokenAccountInstruction({ - from: sendAddress, - to: receiveAddress!, - tokenId: contractAddress, - }) - : { instruction: undefined, destinationTokenAccount: undefined } - - const maybeSwapResponse = await getJupiterSwapInstructions({ - apiUrl: jupiterUrl, - fromAddress: sendAddress, - toAddress: isCrossAccountTrade ? destinationTokenAccount?.toString() : undefined, - rawQuote: quoteResponse, - wrapAndUnwrapSol: buyAsset.assetId === wrappedSolAssetId ? false : true, - // Shared account is not supported for simple AMMs - useSharedAccounts: quoteResponse.routePlan.length > 1 && isCrossAccountTrade ? true : false, - }) - - if (maybeSwapResponse.isErr()) { - const error = maybeSwapResponse.unwrapErr() - const cause = error.cause as AxiosError - throw Error(cause.response!.data.detail) - } - - const { data: swapResponse } = maybeSwapResponse.unwrap() - - const convertJupiterInstruction = (instruction: Instruction): TransactionInstruction => ({ - ...instruction, - keys: instruction.accounts.map(account => ({ - ...account, - pubkey: new PublicKey(account.pubkey), - })), - data: Buffer.from(instruction.data, 'base64'), - programId: new PublicKey(instruction.programId), - }) - - const instructions: TransactionInstruction[] = [ - ...swapResponse.setupInstructions.map(convertJupiterInstruction), - convertJupiterInstruction(swapResponse.swapInstruction), - ] - - if (createTokenAccountInstruction) { - instructions.unshift(createTokenAccountInstruction) - } - - if (swapResponse.cleanupInstruction) { - instructions.push(convertJupiterInstruction(swapResponse.cleanupInstruction)) - } - - const getFeeData = async () => { - const sellAdapter = deps.assertGetSolanaChainAdapter(sellAsset.chainId) - const getFeeDataInput: GetFeeDataInput = { - to: '', - value: '0', - chainSpecific: { - from: sendAddress, - addressLookupTableAccounts: swapResponse.addressLookupTableAddresses, - instructions, - }, - } - const feeData = await sellAdapter.getFeeData(getFeeDataInput) - return { - txFee: feeData.fast.txFee, - chainSpecific: { - computeUnits: bnOrZero(feeData.fast.chainSpecific.computeUnits) - .times(JUPITER_COMPUTE_UNIT_MARGIN_MULTIPLIER) - .toFixed(0), - priorityFee: feeData.fast.chainSpecific.priorityFee, - }, - } - } - - const protocolFees: Record = quoteResponse.routePlan.reduce( - (acc, route) => { - const feeAssetId = toAssetId({ - assetReference: route.swapInfo.feeMint, - assetNamespace: ASSET_NAMESPACE.splToken, - chainNamespace: CHAIN_NAMESPACE.Solana, - chainReference: CHAIN_REFERENCE.SolanaMainnet, - }) - const feeAsset = assetsById[feeAssetId] - - // If we can't find the feeAsset, we can't provide a protocol fee to display - // But these fees exists at protocol level, it's mostly to make TS happy as we should have the market data and assets - if (!feeAsset) return acc - - acc[feeAssetId] = { - requiresBalance: false, - amountCryptoBaseUnit: bnOrZero(route.swapInfo.feeAmount).toFixed(0), - asset: feeAsset, - } - - return acc - }, - {} as Record, - ) - - const getQuoteRate = (sellAmountCryptoBaseUnit: string, buyAmountCryptoBaseUnit: string) => { - return getRate({ - sellAmountCryptoBaseUnit, - buyAmountCryptoBaseUnit, - sellAsset, - buyAsset, - }) - } - - const quotes: TradeQuote[] = [] - - const feeData = await getFeeData() - - const rate = getQuoteRate(quoteResponse.inAmount, quoteResponse.outAmount) - - const tradeQuote: TradeQuote = { - id: uuid(), - rate, - potentialAffiliateBps: affiliateBps, - affiliateBps, - receiveAddress, - slippageTolerancePercentageDecimal: - slippageTolerancePercentageDecimal ?? - getDefaultSlippageDecimalPercentageForSwapper(SwapperName.Jupiter), - steps: [ - { - accountNumber, - buyAmountBeforeFeesCryptoBaseUnit: quoteResponse.outAmount, - buyAmountAfterFeesCryptoBaseUnit: quoteResponse.outAmount, - sellAmountIncludingProtocolFeesCryptoBaseUnit: quoteResponse.inAmount, - jupiterQuoteResponse: quoteResponse, - jupiterTransactionMetadata: { - addressLookupTableAddresses: swapResponse.addressLookupTableAddresses, - instructions, - }, - feeData: { - protocolFees, - networkFeeCryptoBaseUnit: feeData.txFee, - chainSpecific: feeData.chainSpecific, - }, - rate, - source: SwapperName.Jupiter, - buyAsset, - sellAsset, - allowanceContract: '0x0', - estimatedExecutionTimeMs: quoteResponse.timeTaken! * 1000, - }, - ], - } - - quotes.push(tradeQuote) - - return Ok(quotes) - }, + getTradeRate, + getTradeQuote, getUnsignedSolanaTransaction: async ({ tradeQuote, from, diff --git a/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeQuote.ts b/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeQuote.ts new file mode 100644 index 00000000000..9bb4101427e --- /dev/null +++ b/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeQuote.ts @@ -0,0 +1,273 @@ +import type { Instruction } from '@jup-ag/api' +import type { AssetId } from '@shapeshiftoss/caip' +import { + ASSET_NAMESPACE, + CHAIN_NAMESPACE, + CHAIN_REFERENCE, + fromAssetId, + solAssetId, + toAssetId, + wrappedSolAssetId, +} from '@shapeshiftoss/caip' +import type { GetFeeDataInput } from '@shapeshiftoss/chain-adapters' +import type { KnownChainIds } from '@shapeshiftoss/types' +import { bnOrZero, convertDecimalPercentageToBasisPoints } from '@shapeshiftoss/utils' +import type { Result } from '@sniptt/monads' +import { Err, Ok } from '@sniptt/monads' +import type { TransactionInstruction } from '@solana/web3.js' +import { PublicKey } from '@solana/web3.js' +import type { AxiosError } from 'axios' +import { v4 as uuid } from 'uuid' + +import { getDefaultSlippageDecimalPercentageForSwapper } from '../../..' +import type { + CommonTradeQuoteInput, + ProtocolFee, + SwapErrorRight, + SwapperDeps, + TradeQuote, +} from '../../../types' +import { SwapperName, TradeQuoteError } from '../../../types' +import { getRate, makeSwapErrorRight } from '../../../utils' +import { JUPITER_COMPUTE_UNIT_MARGIN_MULTIPLIER } from '../utils/constants' +import { getJupiterPrice, getJupiterSwapInstructions, isSupportedChainId } from '../utils/helpers' + +export const getTradeQuote = async ( + input: CommonTradeQuoteInput, + deps: SwapperDeps, +): Promise> => { + const { + sellAsset, + buyAsset, + affiliateBps, + receiveAddress, + accountNumber, + sendAddress, + sellAmountIncludingProtocolFeesCryptoBaseUnit: sellAmount, + slippageTolerancePercentageDecimal, + } = input + + const { assetsById } = deps + + const jupiterUrl = deps.config.REACT_APP_JUPITER_API_URL + + if (accountNumber === undefined) { + return Err( + makeSwapErrorRight({ + message: `accountNumber is required`, + code: TradeQuoteError.UnknownError, + }), + ) + } + + if (!isSupportedChainId(sellAsset.chainId)) { + return Err( + makeSwapErrorRight({ + message: `unsupported chainId`, + code: TradeQuoteError.UnsupportedChain, + details: { chainId: sellAsset.chainId }, + }), + ) + } + + if (!isSupportedChainId(buyAsset.chainId)) { + return Err( + makeSwapErrorRight({ + message: `unsupported chainId`, + code: TradeQuoteError.UnsupportedChain, + details: { chainId: sellAsset.chainId }, + }), + ) + } + + if (!sendAddress) { + return Err( + makeSwapErrorRight({ + message: `sendAddress is required`, + code: TradeQuoteError.UnknownError, + }), + ) + } + + const maybePriceResponse = await getJupiterPrice({ + apiUrl: jupiterUrl, + sourceAsset: sellAsset.assetId === solAssetId ? wrappedSolAssetId : sellAsset.assetId, + destinationAsset: buyAsset.assetId === solAssetId ? wrappedSolAssetId : buyAsset.assetId, + commissionBps: affiliateBps, + amount: sellAmount, + slippageBps: convertDecimalPercentageToBasisPoints( + slippageTolerancePercentageDecimal ?? + getDefaultSlippageDecimalPercentageForSwapper(SwapperName.Jupiter), + ).toFixed(), + }) + + if (maybePriceResponse.isErr()) { + return Err( + makeSwapErrorRight({ + message: 'Quote request failed', + code: TradeQuoteError.NoRouteFound, + }), + ) + } + + const { data: quoteResponse } = maybePriceResponse.unwrap() + + const contractAddress = + buyAsset.assetId === solAssetId ? undefined : fromAssetId(buyAsset.assetId).assetReference + + const adapter = deps.assertGetSolanaChainAdapter(sellAsset.chainId) + + const isCrossAccountTrade = receiveAddress ? receiveAddress !== sendAddress : false + + const { instruction: createTokenAccountInstruction, destinationTokenAccount } = + contractAddress && isCrossAccountTrade + ? await adapter.createAssociatedTokenAccountInstruction({ + from: sendAddress, + to: receiveAddress!, + tokenId: contractAddress, + }) + : { instruction: undefined, destinationTokenAccount: undefined } + + const maybeSwapResponse = await getJupiterSwapInstructions({ + apiUrl: jupiterUrl, + fromAddress: sendAddress, + toAddress: isCrossAccountTrade ? destinationTokenAccount?.toString() : undefined, + rawQuote: quoteResponse, + wrapAndUnwrapSol: buyAsset.assetId === wrappedSolAssetId ? false : true, + // Shared account is not supported for simple AMMs + useSharedAccounts: quoteResponse.routePlan.length > 1 && isCrossAccountTrade ? true : false, + }) + + if (maybeSwapResponse.isErr()) { + const error = maybeSwapResponse.unwrapErr() + const cause = error.cause as AxiosError + throw Error(cause.response!.data.detail) + } + + const { data: swapResponse } = maybeSwapResponse.unwrap() + + const convertJupiterInstruction = (instruction: Instruction): TransactionInstruction => ({ + ...instruction, + keys: instruction.accounts.map(account => ({ + ...account, + pubkey: new PublicKey(account.pubkey), + })), + data: Buffer.from(instruction.data, 'base64'), + programId: new PublicKey(instruction.programId), + }) + + const instructions: TransactionInstruction[] = [ + ...swapResponse.setupInstructions.map(convertJupiterInstruction), + convertJupiterInstruction(swapResponse.swapInstruction), + ] + + if (createTokenAccountInstruction) { + instructions.unshift(createTokenAccountInstruction) + } + + if (swapResponse.cleanupInstruction) { + instructions.push(convertJupiterInstruction(swapResponse.cleanupInstruction)) + } + + const getFeeData = async () => { + const sellAdapter = deps.assertGetSolanaChainAdapter(sellAsset.chainId) + const getFeeDataInput: GetFeeDataInput = { + to: '', + value: '0', + chainSpecific: { + from: sendAddress, + addressLookupTableAccounts: swapResponse.addressLookupTableAddresses, + instructions, + }, + } + const feeData = await sellAdapter.getFeeData(getFeeDataInput) + return { + txFee: feeData.fast.txFee, + chainSpecific: { + computeUnits: bnOrZero(feeData.fast.chainSpecific.computeUnits) + .times(JUPITER_COMPUTE_UNIT_MARGIN_MULTIPLIER) + .toFixed(0), + priorityFee: feeData.fast.chainSpecific.priorityFee, + }, + } + } + + const protocolFees: Record = quoteResponse.routePlan.reduce( + (acc, route) => { + const feeAssetId = toAssetId({ + assetReference: route.swapInfo.feeMint, + assetNamespace: ASSET_NAMESPACE.splToken, + chainNamespace: CHAIN_NAMESPACE.Solana, + chainReference: CHAIN_REFERENCE.SolanaMainnet, + }) + const feeAsset = assetsById[feeAssetId] + + // If we can't find the feeAsset, we can't provide a protocol fee to display + // But these fees exists at protocol level, it's mostly to make TS happy as we should have the market data and assets + if (!feeAsset) return acc + + acc[feeAssetId] = { + requiresBalance: false, + amountCryptoBaseUnit: bnOrZero(route.swapInfo.feeAmount).toFixed(0), + asset: feeAsset, + } + + return acc + }, + {} as Record, + ) + + const getQuoteRate = (sellAmountCryptoBaseUnit: string, buyAmountCryptoBaseUnit: string) => { + return getRate({ + sellAmountCryptoBaseUnit, + buyAmountCryptoBaseUnit, + sellAsset, + buyAsset, + }) + } + + const quotes: TradeQuote[] = [] + + const feeData = await getFeeData() + + const rate = getQuoteRate(quoteResponse.inAmount, quoteResponse.outAmount) + + const tradeQuote: TradeQuote = { + id: uuid(), + rate, + potentialAffiliateBps: affiliateBps, + affiliateBps, + receiveAddress, + slippageTolerancePercentageDecimal: + slippageTolerancePercentageDecimal ?? + getDefaultSlippageDecimalPercentageForSwapper(SwapperName.Jupiter), + steps: [ + { + accountNumber, + buyAmountBeforeFeesCryptoBaseUnit: quoteResponse.outAmount, + buyAmountAfterFeesCryptoBaseUnit: quoteResponse.outAmount, + sellAmountIncludingProtocolFeesCryptoBaseUnit: quoteResponse.inAmount, + jupiterQuoteResponse: quoteResponse, + jupiterTransactionMetadata: { + addressLookupTableAddresses: swapResponse.addressLookupTableAddresses, + instructions, + }, + feeData: { + protocolFees, + networkFeeCryptoBaseUnit: feeData.txFee, + chainSpecific: feeData.chainSpecific, + }, + rate, + source: SwapperName.Jupiter, + buyAsset, + sellAsset, + allowanceContract: '0x0', + estimatedExecutionTimeMs: quoteResponse.timeTaken! * 1000, + }, + ], + } + + quotes.push(tradeQuote) + + return Ok(quotes) +} diff --git a/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeRate.ts b/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeRate.ts new file mode 100644 index 00000000000..2c3c514bf05 --- /dev/null +++ b/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeRate.ts @@ -0,0 +1,193 @@ +import type { AssetId } from '@shapeshiftoss/caip' +import { + ASSET_NAMESPACE, + CHAIN_NAMESPACE, + CHAIN_REFERENCE, + fromAssetId, + solAssetId, + toAssetId, + wrappedSolAssetId, +} from '@shapeshiftoss/caip' +import type { GetFeeDataInput } from '@shapeshiftoss/chain-adapters' +import type { KnownChainIds } from '@shapeshiftoss/types' +import { bnOrZero, convertDecimalPercentageToBasisPoints } from '@shapeshiftoss/utils' +import type { Result } from '@sniptt/monads' +import { Err, Ok } from '@sniptt/monads' +import { v4 as uuid } from 'uuid' + +import { getDefaultSlippageDecimalPercentageForSwapper } from '../../..' +import type { + GetTradeRateInput, + ProtocolFee, + SwapErrorRight, + SwapperDeps, + TradeRate, +} from '../../../types' +import { SwapperName, TradeQuoteError } from '../../../types' +import { getRate, makeSwapErrorRight } from '../../../utils' +import { SOLANA_RANDOM_ADDRESS } from '../utils/constants' +import { getJupiterPrice, isSupportedChainId } from '../utils/helpers' + +export const getTradeRate = async ( + input: GetTradeRateInput, + deps: SwapperDeps, +): Promise> => { + const { + sellAsset, + buyAsset, + sellAmountIncludingProtocolFeesCryptoBaseUnit: sellAmount, + affiliateBps, + receiveAddress, + accountNumber, + slippageTolerancePercentageDecimal, + } = input + + const { assetsById } = deps + + const jupiterUrl = deps.config.REACT_APP_JUPITER_API_URL + + if (!isSupportedChainId(sellAsset.chainId)) { + return Err( + makeSwapErrorRight({ + message: `unsupported chainId`, + code: TradeQuoteError.UnsupportedChain, + details: { chainId: sellAsset.chainId }, + }), + ) + } + + if (!isSupportedChainId(buyAsset.chainId)) { + return Err( + makeSwapErrorRight({ + message: `unsupported chainId`, + code: TradeQuoteError.UnsupportedChain, + details: { chainId: sellAsset.chainId }, + }), + ) + } + + if (buyAsset.assetId === wrappedSolAssetId || sellAsset.assetId === wrappedSolAssetId) { + return Err( + makeSwapErrorRight({ + message: `Unsupported trade pair`, + code: TradeQuoteError.UnsupportedTradePair, + }), + ) + } + + const maybePriceResponse = await getJupiterPrice({ + apiUrl: jupiterUrl, + sourceAsset: sellAsset.assetId === solAssetId ? wrappedSolAssetId : sellAsset.assetId, + destinationAsset: buyAsset.assetId === solAssetId ? wrappedSolAssetId : buyAsset.assetId, + commissionBps: affiliateBps, + amount: sellAmount, + slippageBps: convertDecimalPercentageToBasisPoints( + slippageTolerancePercentageDecimal ?? + getDefaultSlippageDecimalPercentageForSwapper(SwapperName.Jupiter), + ).toFixed(), + }) + + if (maybePriceResponse.isErr()) { + return Err( + makeSwapErrorRight({ + message: 'Quote request failed', + code: TradeQuoteError.NoRouteFound, + }), + ) + } + + const { data: quoteResponse } = maybePriceResponse.unwrap() + + const getFeeData = async () => { + const sellAdapter = deps.assertGetSolanaChainAdapter(sellAsset.chainId) + const getFeeDataInput: GetFeeDataInput = { + // used as a placeholder for the sake of loosely estimating fees + to: SOLANA_RANDOM_ADDRESS, + value: sellAmount, + chainSpecific: { + from: SOLANA_RANDOM_ADDRESS, + tokenId: + sellAsset.assetId === solAssetId + ? undefined + : fromAssetId(sellAsset.assetId).assetReference, + }, + } + const { fast } = await sellAdapter.getFeeData(getFeeDataInput) + return { networkFeeCryptoBaseUnit: fast.txFee } + } + + const protocolFees: Record = quoteResponse.routePlan.reduce( + (acc, route) => { + const feeAssetId = toAssetId({ + assetReference: route.swapInfo.feeMint, + assetNamespace: ASSET_NAMESPACE.splToken, + chainNamespace: CHAIN_NAMESPACE.Solana, + chainReference: CHAIN_REFERENCE.SolanaMainnet, + }) + const feeAsset = assetsById[feeAssetId] + + // If we can't find the feeAsset, we can't provide a protocol fee to display + // But these fees exists at protocol level, it's mostly to make TS happy as we should have the market data and assets + if (!feeAsset) return acc + + acc[feeAssetId] = { + requiresBalance: false, + amountCryptoBaseUnit: bnOrZero(route.swapInfo.feeAmount).toFixed(0), + asset: feeAsset, + } + + return acc + }, + {} as Record, + ) + + const getQuoteRate = (sellAmountCryptoBaseUnit: string, buyAmountCryptoBaseUnit: string) => { + return getRate({ + sellAmountCryptoBaseUnit, + buyAmountCryptoBaseUnit, + sellAsset, + buyAsset, + }) + } + + const rates: TradeRate[] = [] + + const feeData = await getFeeData() + + const rate = getQuoteRate(quoteResponse.inAmount, quoteResponse.outAmount) + + const tradeRate: TradeRate = { + id: uuid(), + rate, + receiveAddress, + potentialAffiliateBps: affiliateBps, + affiliateBps, + accountNumber, + slippageTolerancePercentageDecimal: + slippageTolerancePercentageDecimal ?? + getDefaultSlippageDecimalPercentageForSwapper(SwapperName.Jupiter), + steps: [ + { + buyAmountBeforeFeesCryptoBaseUnit: quoteResponse.outAmount, + buyAmountAfterFeesCryptoBaseUnit: quoteResponse.outAmount, + sellAmountIncludingProtocolFeesCryptoBaseUnit: quoteResponse.inAmount, + jupiterQuoteResponse: quoteResponse, + feeData: { + protocolFees, + ...feeData, + }, + rate, + source: SwapperName.Jupiter, + buyAsset, + sellAsset, + accountNumber, + allowanceContract: '0x0', + estimatedExecutionTimeMs: quoteResponse.timeTaken! * 1000, + }, + ], + } + + rates.push(tradeRate) + + return Ok(rates) +} From 561cd0854969e274843124d716a24964dec5892e Mon Sep 17 00:00:00 2001 From: NeOMakinG <14963751+NeOMakinG@users.noreply.github.com> Date: Thu, 28 Nov 2024 09:40:53 +0100 Subject: [PATCH 127/127] fix: review feedbacks --- .../src/swappers/JupiterSwapper/swapperApi/getTradeQuote.ts | 4 ++-- .../src/swappers/JupiterSwapper/swapperApi/getTradeRate.ts | 3 ++- packages/swapper/src/swappers/JupiterSwapper/utils/helpers.ts | 3 --- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeQuote.ts b/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeQuote.ts index 9bb4101427e..e050a4b36d3 100644 --- a/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeQuote.ts +++ b/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeQuote.ts @@ -133,7 +133,6 @@ export const getTradeQuote = async ( fromAddress: sendAddress, toAddress: isCrossAccountTrade ? destinationTokenAccount?.toString() : undefined, rawQuote: quoteResponse, - wrapAndUnwrapSol: buyAsset.assetId === wrappedSolAssetId ? false : true, // Shared account is not supported for simple AMMs useSharedAccounts: quoteResponse.routePlan.length > 1 && isCrossAccountTrade ? true : false, }) @@ -262,7 +261,8 @@ export const getTradeQuote = async ( buyAsset, sellAsset, allowanceContract: '0x0', - estimatedExecutionTimeMs: quoteResponse.timeTaken! * 1000, + // Swap are so fasts on solana that times are under 100ms displaying 0 or very small amount of time is not user friendly + estimatedExecutionTimeMs: undefined, }, ], } diff --git a/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeRate.ts b/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeRate.ts index 2c3c514bf05..27f8f2838fc 100644 --- a/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeRate.ts +++ b/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeRate.ts @@ -182,7 +182,8 @@ export const getTradeRate = async ( sellAsset, accountNumber, allowanceContract: '0x0', - estimatedExecutionTimeMs: quoteResponse.timeTaken! * 1000, + // Swap are so fasts on solana that times are under 100ms displaying 0 or very small amount of time is not user friendly + estimatedExecutionTimeMs: undefined, }, ], } diff --git a/packages/swapper/src/swappers/JupiterSwapper/utils/helpers.ts b/packages/swapper/src/swappers/JupiterSwapper/utils/helpers.ts index b0442c4b74e..eae52dceb79 100644 --- a/packages/swapper/src/swappers/JupiterSwapper/utils/helpers.ts +++ b/packages/swapper/src/swappers/JupiterSwapper/utils/helpers.ts @@ -30,7 +30,6 @@ type GetJupiterSwapArgs = { rawQuote: unknown toAddress?: string useSharedAccounts: boolean - wrapAndUnwrapSol: boolean } export const getJupiterPrice = ({ @@ -58,7 +57,6 @@ export const getJupiterSwapInstructions = ({ toAddress, rawQuote, useSharedAccounts, - wrapAndUnwrapSol, }: GetJupiterSwapArgs): Promise< Result, SwapErrorRight> > => @@ -69,5 +67,4 @@ export const getJupiterSwapInstructions = ({ quoteResponse: rawQuote, dynamicComputeUnitLimit: true, prioritizationFeeLamports: 'auto', - wrapAndUnwrapSol, })