From 7bed9c04d175ae61be2192107401b90560a0b5b4 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 2 Jun 2026 16:31:33 +0500 Subject: [PATCH 1/6] Updated on 2026-08-14 --- app/src/main/java/com/tangem/tap/MainActivity.kt | 4 ++-- .../deeplink/PayloadToDeeplinkConverterTest.kt | 8 ++++---- .../visa/model/TangemPayPushNotificationType.kt | 6 ++++-- .../TangemPayTxHistoryDetailsConverter.kt | 2 +- .../deeplink/DefaultTangemPayMainDeepLinkHandler.kt | 12 ++++++------ .../tangempay/deeplink/TangemPayPushAction.kt | 6 ++---- 6 files changed, 19 insertions(+), 19 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/MainActivity.kt b/app/src/main/java/com/tangem/tap/MainActivity.kt index e998374c66..b2aa247f2c 100644 --- a/app/src/main/java/com/tangem/tap/MainActivity.kt +++ b/app/src/main/java/com/tangem/tap/MainActivity.kt @@ -19,10 +19,10 @@ import androidx.appcompat.app.AppCompatDelegate.setDefaultNightMode import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.ui.Modifier -import androidx.compose.ui.semantics.semantics -import androidx.compose.ui.semantics.testTagsAsResourceId import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.toArgb +import androidx.compose.ui.semantics.semantics +import androidx.compose.ui.semantics.testTagsAsResourceId import androidx.core.net.toUri import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen import androidx.lifecycle.flowWithLifecycle diff --git a/common/routing/src/test/kotlin/com/tangem/common/routing/deeplink/PayloadToDeeplinkConverterTest.kt b/common/routing/src/test/kotlin/com/tangem/common/routing/deeplink/PayloadToDeeplinkConverterTest.kt index 8dd6c1ba5d..d60ee79c7c 100644 --- a/common/routing/src/test/kotlin/com/tangem/common/routing/deeplink/PayloadToDeeplinkConverterTest.kt +++ b/common/routing/src/test/kotlin/com/tangem/common/routing/deeplink/PayloadToDeeplinkConverterTest.kt @@ -1,8 +1,8 @@ package com.tangem.common.routing.deeplink import com.google.common.truth.Truth.assertThat -import com.tangem.common.routing.deeplink.DeeplinkConst.DEEPLINK_KEY import com.tangem.common.routing.deeplink.DeeplinkConst.CUSTOMER_WALLET_ID_KEY +import com.tangem.common.routing.deeplink.DeeplinkConst.DEEPLINK_KEY import com.tangem.common.routing.deeplink.DeeplinkConst.DERIVATION_PATH_KEY import com.tangem.common.routing.deeplink.DeeplinkConst.NETWORK_ID_KEY import com.tangem.common.routing.deeplink.DeeplinkConst.TOKEN_ID_KEY @@ -188,7 +188,7 @@ internal class PayloadToDeeplinkConverterTest { fun `GIVEN tangem pay top_up push payload WHEN convert THEN should return pay-app-main deeplink`() { // GIVEN val payload = mapOf( - TYPE_KEY to TangemPayPushNotificationType.TOP_UP.value, + TYPE_KEY to TangemPayPushNotificationType.DECLINED_TOP_UP.value, CUSTOMER_WALLET_ID_KEY to "wallet123", TRANSACTION_ID_KEY to "test456", ) @@ -206,7 +206,7 @@ internal class PayloadToDeeplinkConverterTest { fun `GIVEN tangem pay collateral push payload WHEN convert THEN should return pay-app-main deeplink`() { // GIVEN val payload = mapOf( - TYPE_KEY to TangemPayPushNotificationType.COLLATERAL.value, + TYPE_KEY to TangemPayPushNotificationType.COLLATERAL_DEPOSIT.value, CUSTOMER_WALLET_ID_KEY to "wallet123", ) @@ -215,7 +215,7 @@ internal class PayloadToDeeplinkConverterTest { // THEN assertThat(result).isEqualTo( - "tangem://pay-app-main?type=collateral&customer_wallet_id=wallet123", + "tangem://pay-app-main?type=collateral_deposit&customer_wallet_id=wallet123", ) } diff --git a/domain/visa/models/src/main/kotlin/com/tangem/domain/visa/model/TangemPayPushNotificationType.kt b/domain/visa/models/src/main/kotlin/com/tangem/domain/visa/model/TangemPayPushNotificationType.kt index 1ff9b157c8..a45bf3886f 100644 --- a/domain/visa/models/src/main/kotlin/com/tangem/domain/visa/model/TangemPayPushNotificationType.kt +++ b/domain/visa/models/src/main/kotlin/com/tangem/domain/visa/model/TangemPayPushNotificationType.kt @@ -3,8 +3,10 @@ package com.tangem.domain.visa.model enum class TangemPayPushNotificationType(val value: String) { CARD_READY("card_ready"), TRANSACTION_SPEND("transaction_spend"), - TOP_UP("declined_top_up"), - COLLATERAL("collateral"), + DECLINED_TOP_UP("declined_top_up"), + COLLATERAL_WITHDRAW("collateral_withdraw"), + COLLATERAL_DEPOSIT("collateral_deposit"), + TRANSACTION_SPEND_REFUND("transaction_spend_refund"), ; companion object { diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/transformers/TangemPayTxHistoryDetailsConverter.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/transformers/TangemPayTxHistoryDetailsConverter.kt index b15f718595..770d13241b 100644 --- a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/transformers/TangemPayTxHistoryDetailsConverter.kt +++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/transformers/TangemPayTxHistoryDetailsConverter.kt @@ -62,7 +62,7 @@ internal object TangemPayTxHistoryDetailsConverter : is TangemPayTxHistoryItem.Payment -> ImageReference.Res(R.drawable.ic_arrow_up_24) is TangemPayTxHistoryItem.Spend -> { val merchantIcon = this.enrichedMerchantIconUrl - if (merchantIcon != null) { + if (!merchantIcon.isNullOrEmpty()) { ImageReference.Url(merchantIcon) } else { ImageReference.Res(R.drawable.ic_category_24) diff --git a/features/tangempay/onboarding/impl/src/main/kotlin/com/tangem/features/tangempay/deeplink/DefaultTangemPayMainDeepLinkHandler.kt b/features/tangempay/onboarding/impl/src/main/kotlin/com/tangem/features/tangempay/deeplink/DefaultTangemPayMainDeepLinkHandler.kt index d130d1683f..ef2a0b7745 100644 --- a/features/tangempay/onboarding/impl/src/main/kotlin/com/tangem/features/tangempay/deeplink/DefaultTangemPayMainDeepLinkHandler.kt +++ b/features/tangempay/onboarding/impl/src/main/kotlin/com/tangem/features/tangempay/deeplink/DefaultTangemPayMainDeepLinkHandler.kt @@ -61,9 +61,7 @@ internal class DefaultTangemPayMainDeepLinkHandler @AssistedInject constructor( onComplete = { walletDeepLinkActionTrigger.selectWallet(userWalletId) when (pushAction) { - is TangemPayPushAction.CardReady, - is TangemPayPushAction.TopUp, - -> navigateToTangemPayDetails(userWalletId) + is TangemPayPushAction.CardReady -> navigateToTangemPayDetails(userWalletId) is TangemPayPushAction.TransactionSpend -> { walletDeepLinkActionTrigger.showTangemPayTransaction( transaction = pushAction.transaction, @@ -89,12 +87,14 @@ internal class DefaultTangemPayMainDeepLinkHandler @AssistedInject constructor( return when (type) { TangemPayPushNotificationType.CARD_READY -> TangemPayPushAction.CardReady - TangemPayPushNotificationType.TRANSACTION_SPEND -> { + TangemPayPushNotificationType.TRANSACTION_SPEND, + TangemPayPushNotificationType.TRANSACTION_SPEND_REFUND, + TangemPayPushNotificationType.DECLINED_TOP_UP, + -> { val transaction = TangemPayPushPayloadToTxHistoryItemConverter.convertSpend(payload) if (transaction != null) TangemPayPushAction.TransactionSpend(transaction, customerId) else null } - TangemPayPushNotificationType.TOP_UP -> TangemPayPushAction.TopUp - TangemPayPushNotificationType.COLLATERAL -> { + TangemPayPushNotificationType.COLLATERAL_DEPOSIT, TangemPayPushNotificationType.COLLATERAL_WITHDRAW -> { val transaction = TangemPayPushPayloadToTxHistoryItemConverter.convertCollateral(payload) if (transaction != null) TangemPayPushAction.CollateralTransaction(transaction, customerId) else null } diff --git a/features/tangempay/onboarding/impl/src/main/kotlin/com/tangem/features/tangempay/deeplink/TangemPayPushAction.kt b/features/tangempay/onboarding/impl/src/main/kotlin/com/tangem/features/tangempay/deeplink/TangemPayPushAction.kt index 4ae61bc268..2808e28da9 100644 --- a/features/tangempay/onboarding/impl/src/main/kotlin/com/tangem/features/tangempay/deeplink/TangemPayPushAction.kt +++ b/features/tangempay/onboarding/impl/src/main/kotlin/com/tangem/features/tangempay/deeplink/TangemPayPushAction.kt @@ -7,14 +7,12 @@ internal sealed class TangemPayPushAction { data object CardReady : TangemPayPushAction() data class TransactionSpend( - val transaction: TangemPayTxHistoryItem, + val transaction: TangemPayTxHistoryItem.Spend, val customerId: String, ) : TangemPayPushAction() - data object TopUp : TangemPayPushAction() - data class CollateralTransaction( - val transaction: TangemPayTxHistoryItem, + val transaction: TangemPayTxHistoryItem.Collateral, val customerId: String, ) : TangemPayPushAction() } \ No newline at end of file From a829b05a4db066e6b51f0443e215547b58366dba Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 2 Jun 2026 16:34:37 +0500 Subject: [PATCH 2/6] Updated on 2026-08-14 --- .../wallet/domain/Wallet2CobrandImage.kt | 12 ++++++++++++ .../res/drawable/ill_nanovest_card2_120_106.webp | Bin 0 -> 7852 bytes .../res/drawable/ill_nanovest_card3_120_106.webp | Bin 0 -> 9030 bytes .../drawable/ill_superteam_card2_120_106.webp | Bin 0 -> 5660 bytes .../drawable/ill_superteam_card3_120_106.webp | Bin 0 -> 5920 bytes 5 files changed, 12 insertions(+) create mode 100644 features/wallet/impl/src/main/res/drawable/ill_nanovest_card2_120_106.webp create mode 100644 features/wallet/impl/src/main/res/drawable/ill_nanovest_card3_120_106.webp create mode 100644 features/wallet/impl/src/main/res/drawable/ill_superteam_card2_120_106.webp create mode 100644 features/wallet/impl/src/main/res/drawable/ill_superteam_card3_120_106.webp diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/Wallet2CobrandImage.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/Wallet2CobrandImage.kt index c6a3e8632a..719e0b1dc9 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/Wallet2CobrandImage.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/Wallet2CobrandImage.kt @@ -422,4 +422,16 @@ internal enum class Wallet2CobrandImage( cards3ResId = R.drawable.ill_stronghold_card3_120_106, batchIds = setOf("BB000054"), ), + + Superteam( + cards2ResId = R.drawable.ill_superteam_card2_120_106, + cards3ResId = R.drawable.ill_superteam_card3_120_106, + batchIds = setOf("BB000051"), + ), + + Nanovest( + cards2ResId = R.drawable.ill_nanovest_card2_120_106, + cards3ResId = R.drawable.ill_nanovest_card3_120_106, + batchIds = setOf("BB000052"), + ), } \ No newline at end of file diff --git a/features/wallet/impl/src/main/res/drawable/ill_nanovest_card2_120_106.webp b/features/wallet/impl/src/main/res/drawable/ill_nanovest_card2_120_106.webp new file mode 100644 index 0000000000000000000000000000000000000000..1be5b7172e140867bc4dbe4072e266b710fbdb14 GIT binary patch literal 7852 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 O&c8PWSZe>tr2hf^qf^%a literal 0 HcmV?d00001 diff --git a/features/wallet/impl/src/main/res/drawable/ill_nanovest_card3_120_106.webp b/features/wallet/impl/src/main/res/drawable/ill_nanovest_card3_120_106.webp new file mode 100644 index 0000000000000000000000000000000000000000..6504ae71d67b2b7fc28fb61c7ea81d12549f9677 GIT binary patch literal 9030 zcmV-MBe~pCNk&FKBLDzbMM6+kP&il$0000G0002r0RX1~06|PpNKgj=01X_qZQC%` z|8Kiw${Z0BfY%{D-SSjg005YcrKu6CZHidM>z-}fwr$(~vu)eHPusS=EHXJ?o2G5% zYa_x90JLob>8>&r@JjnjavMpKBscGUng73b!moK1G?^ZsMrf6V)jdH=Cq6-j3E0>`G|^p8J%@lzWukt8a5-IAG>3jl~>98Lc8 z^zH9L6hth^mMptkCT6|=R*)EFt-01u7d;G74$(LxnzmEIr=bUWBeCorljpzUqM2CG zCDSpA_*@6}>lT}D`_y@D#L@~pSE)M-h&j)%k{*Asc+hW%gm_let*T9TUC-xC+;Z&$ ze?gz>7FTy{h3~ZBVAguw#yJpK<`>D(C8M^8l!SxzlKsE93q`&g7bM4+5HlSw0Nao{ z=<=V@;=8G$(`;5U)6fgdmMrAlf(Y|V5Mp_vz6kGnfh!X3c~j^QiQ*N*)Fkn**kIBq zJsalhTeQCL;tD?rgWW2=&b?kx@;`|&Oa@H<^6O+L1Qp6Lw&FAwlcOFO0YjN*y}#jwp{Jno7*9xi3BTFEWIWU zt6w%>_j4CT(^S5q=&F_KU-zXG$s;};|3T3x#+qiMB6NoO2pAtje`2#_*)S}D@oyJJ z*5CD{SH`(mMAJFF-joHmJNze?^p)GM2atkoI|`ZdzioZN@yC8JmR%r;=SqfFEyqSi z!H1r0^_uw!TqtO=A=86Pef{Kpe;czUw=`RLd6CyYKty; z2^^OOpJJrigeHR4DB90S*!|DU7b;FwDJ5qEVpp+)AADyFwpe45*|e05JHm1vz`u~d z3W`;gBsXA*&u(zdI5YSJRj{18#LSJl>Pf6zHZ4n}1G;;*yK81V89bI(t-8u~N8`vy z?5=o_&8i?jH*O3*Sx{>YTNtq&W5M34jqVvAT9MAncFifkurZo>nU`8);Jay7(wmCv zbvzJ4SZ@6=+IxoCO10XMlP(A^Wav)@bgsrRjv>;K+26kZp*5ubPI0Eauz|Hf*kK~~ zmEZlcDU#0_vL+=Xt*+~(h^+hOL(hEg4V6|UYXMCu{3Yw(KJnhc(+*lVaZM*Wt_rYLm z1;&@ng=?i*4}>o!I=#0$r3hA3bW0)IKBP>ZlBP=%mzeDg;8;d>DV^>Hr95LAqoG`pfvZ3sdm)uq*9QH-^MAimg9 z=YKy~gXe0Eg=B2f^+34f#v2FdI4(&(KA8E%NnSS>t{1vt^}3!&khWo$YyFOm;G$+r zCY$mAB5~>Od=(3|xu8yg4nQhqmiA{9J0+=$*32|OGOpaW2T}IK!m`i;=tiy27T6Vb zGg<)gDE8wA_(nTJfPN(UxHS%k00o)o{kGHQ01X-I`R9lBHUJ_b((Br6TLWmzB{xUh z8*wJ;{^h}b5OGmn11UA4Cu|B47g^Me0abvySlvV2=v4tg+qc;Q>b_Rz&=Ot`a3Jd5 z>Bt)?0mOX~p;7m-|KZgqUFD_V)>Y=M@UChXM}XgGqwg2Rf%#Q2#5d#RR>AvEOmb{Z>w6y+^YQLR=iKc`ECs6R&>ASg|@nWx#YxE%_Ht?Z@U7%+^YGu8=+e% z6}W5`yxhv)WMZ$KF1jJG*~^_r-+sq5^IX4Na)2iVII;J{({$@*r)5p>a>)VyM-8xK zUBY`cy`G27s{l@1UG(Kv^T@VyzqX>wHB$OU?A5fs+^X?@%MV_oxf;HPTyT>dx|RVv zFP^>8g*UZV6TY7kd`;hW1(ogGukG+n_A{5%*BbAct?#&(0i5W|t^DPZ+xb#C>zO-e z87sK2Rr6wRU1ch=R=N2mz;${#TkxKi6S^N0xqZha9>QgnT^!?Y-FshKPV^nv6z>b~ zZ8W-aNqz0vC@yzx-FqG-{%&?vc~n+e&fK|L-;NY7`fi@^<<7V7yp|JLxz(dYR!U{` zyq2rO5kzxkhmME6q=aX=0~W9_utk1wJ6L(&QB)A2%84NN}})yvTQ z9t5OSXC?;pTWVOxmMOK*a2x-;e>PnFxsL{@)bG8csX1*a2{ic8bqUh7dk?S84h+03 zoUUJ(7nb@HJ=OD*j6i(kp(%mlEZgnpn0ppz{I?)jj}RQUE~Pz0-?}$uF&SAu>0J^{ zSrPU;M!kgQQNV~zX}UuDgbAsORwZcLaDz1Gs2zE|vok!VsdXuzVH>`k{WrlLWgrTE zlYX&kKM-&dZs+jHHcn@<_^v&2#N0zm!VY7m7Q0NxBtOFRM5E@)e*wYxF{vNqv<{)y zk1YEyYgKy0mfAr0OyAI ztuce+54n+(wX484LTzX&o^9VQI2xRj7RJFXrw_D0=*$Q=w7}%AQth-3AB%|$#M^xj z_s2_=61zMpoN8a=kI%lBL28Fl(Ibqphi}6`0L{WYgkSXI=1c^jznNm*0A5^S1BY9d zTo((oeT}K(i;dY{OZe4YP!y>JZi?nXvK`Tbru z8MG*4un?S1xNI z-%+OpuYWs` z9s7CZ6&&Nt zFeptWP2<_M>|fu<{Lq5;lc+f?g(xMPSYIgD-s7#zbUt0(%0F4qf6dwxiM28E4qPYVx&CM3a@|H`NI9n>#tJa6D9Cga`Z>_D2cT-R<_5W zc(hs#E007K;o5}_koV3~yn9Lw90cZEe?N2s(c)loaSTF>;V=f{T3AU{-87=40zG{} zNkv(JsMoXXpd{S8tWOo1z9-SJoEb1=(riLiKj+280{G^)&C zVHNIH>i($_-RcN9in%5_?_gUOhCCb*xUs;P^PH2lG_u-xn8X zb02~>(0}n(&Cde`3-`SrvRUEg=C0Ub5H$V!c^zqle&z$V@Lr6~E_jVa-QKwD0=>b| zp#Lc_zw!8mEPGw?ug;F~^UVp4lCZUGpK>iILU-01jKLv5}<5 zfa<=u;8XSi%`h>w#!c0S-0<8ERh@o;rogK1pPSZfTH(d+__~8}mi`jyX@H|AWaQ#f z`iNqosOGkX&cAb`Q&y{}0JFCIb^gpez3E>7*GGn%(Wx+E`AC^sl%UaFLZ7%kDE9~t z-C6yF(7{2K_xw+_WDogo`+duvk9iXsTV}cN&6VTVx<=(EE4Sa1g5z|X0MPUj1U_G6 z?BnzD0_8Idw9ZkKK?#dO)v%yU%7c>P{LhTngu93bIx``hOy+R#kvfqzrkwnclZ((- zkhn6`;dnGDeM?A>a>W$fCfciH+_vTnAjTUhT+qsG|NRdlzv^b*m7OqU2S!#1d<(X2 zG-iVk+Xr-DffrYmszVj~UO;ZyS8J8cYaYu-f!Bd#V?SzP~7%j{eG z_3(`!`!?7ZT=3qjLWl8U5sKoG)ae0el$>(pM;bA)p6Ph=-GNCsbCtg{Sr4U-|a=O?q zcd(qai?;8N60jQHlsQgto|`i(y;0^g8b0DZpKo)z#l6sqB7GH9>SfJ4eNR!<*_4eR z`~UL*e#hzTaXR_k?o7ly+Bew6Oli+z!T^Obh|6t3)&sEjq?Z5JY}big+nYkMed-tE z7{p8y>TQcl2sUCfi48vlgMI?5vz<6IDU(A9%AYAgb9CljIBS>cAQ6y}zWMeMSB@R% zX=r(J#yukO|J2pC*dQxa#l*&IXjQpbC6?kEsu;%@TaK9 zIWitk2k3Ik#0igwhp2$%6M0L*^qh4bz9UiN`l38B?^ov7l>J~_Lqj)Ki_M`2XF^xAKGl!)EY zWBjs6#`pa~b}dC1RuhUkNmQb&J2z7eFi;hMxHsPr{AnN;YTP^hU-cZSjovKhr8``7 zkx8KO7-6D@jsRa5csXg!{M1v;P&J$J#V4ZzF?@n8v4&7U+582e^0g~*vIqcUH6Nu= zu(kC0UpN5)-&v8C%s*1c`t~2F_$n2o?)1 z`*?mt7v=?^*rNV5m33=&8cntQ+jHTNt(K^ND4hsEljY5@;^%`ApH8v#iiUwRjUs{ZCPf zgVwdue_w-Q^~Px@ndxb#XMA2^5QQNWq8iB>prMmAMbd^T(Z?ep*G30&cV0c&R*btsTVncBaavtRMF-0*x@u*F6%m zFH+N0Y6ja0b)9c^OK^Nc$YkU@|G!dhI1P;V6@-Um0!)6Fl>FXlr_E@MT)2$%|CRN| z!M^`PemcF_#dY5mZa~rvQ~+4*1S&svcJPkq!F}xmcRn|nY?ZKbsLl*<7Q{6%y$WI>CT>; z*Vhp5FZW88aGWx&Bl|7oD?a8?YQl&Heiy8@WlQEigUnVr&$|7MWKoem1f@>_=4xVM z@Q&1;ris+udz=3h8+c@Kt-ed~6T5)*8KxyT#QwBmqyAA4Vxab&jZbsika%RSBuw0Z zZeDUr`o>H?rnBYen6i2S1w5_K*$^6I%N@i<_Yyed^`Cr;?hi6_HdvldAM4p}?D&x&A+Y?I3FVu{{o@4aXhP(*Ri3G}J z1Q(B;6y*?Mk#De8LZSZrxL}l0s&U~Q_*B^IArCH0bzPSL!)$S|N&NGRbz!Vnq*!~y zgR-5Twlo7*(~X++wlHp<{z?OXOW?#YlY{l5GPZX>K#ed8xVj>?URyN`-4296`uS}X z9s0AVbq3@&8W}uN{?2&}I9|JSwivSq>zqd?`re#%B;-qcBoii8Xb}m+KF(ooMin^z zoDK_0typj8LNL)fHV)B_5;x>;doTj8_Z^MI*g6WW^9N8iCG{;S#3Wai=@k*>Yl>;PMO#gzBKg9$8z<$fI{o{>N>>hOJUY??AE`=cHU#Avf0@0;um&SAM4 z+3$={Rl1oXm;tyJ)>ES}keso!y~N@+wFd%Y`|$?~5CC)D9ajl(6?Ly7=FWgcq4p%X z49>7k>S?K5%#lV zZYAn|P`Ap(@V?|8R;&G7v=LrvUBTvq)kPxHI+^iEK5AkL zHHIXR!T#sPj0vk!fd}wfSWF!o1Q;|p1+ovMoDXjlI;duGev1ECn?V+_*BT5xJA9wV z3^fKJ$t@XLX75JI{H3AX-FybRAG&E3pRMK<^!kRehpj~{s#wZDuImK~0TDh`c?UsfZ-lML5mfb_T zfQExF7@w_zXu_x9@{U^UNEfgYy=*Qgf-poZ$%*5V!TG zlPN(XW2LkD-P#sO^@^p?Zq4Fo#9>JDIZn7@aM^A(x7=|}f9-Mo1d1=C+oH*gNz<;` zn$$;1XyLzrkn(TkgR5pc*s> z-L-fV?UW}4>-9dlI75p{E5vDOG7rqw;2HeoGm)g1^o}_d=!Ud`nd%Z!f{8Yw$ep|N zg*xtM_=nR`(1ct9(^QUV`h%k53q~4Q1Mn@PCYS=qw_W0kgrKTpTi$eV*|x! zPT98FG|s-4W~?@6VX&-y5PdCMAH;x(?22i%Y#j;;2q;vSGYRkl^KPT%2V1Arq{b}HwaYx?t zcAKE@$7#qKvcFA@xVpwFdQJM3Ir_cjOAywfm=q7AE zP}OU6#HAV!P}dcWWIkVqCv>JYioES1@Y)t$Mn;jOv4(j-HbN4V*C1|+y=;k#ELm1@p#jtC_sfb%*DQZD#+ z9iPjiJQxP~7BZvr3DF)>B&@HLWb)S4)Ok5|{UsZ#e4IPWc+hhWmacs%_Ajfq2S0+~egtge z;EUToW;QG>U_C}4gc`4dOIiy(fkr2R=Tj=6LMH#O3Es*5cW;;LZkr^gMUpO{tA11A zI80a=6JVQ2Vu`tx>bF9jI^R-KRh>(sfV~OGY*iy2Y3FFW^skRD{d?iu+Z~XtZ)bA? zGf6Y4JqO>G<%C4Qs1D&{l^e15!1TbVRJ)Nu?F}A~G4|-?%NZJ2^2#p4ZD-FXE=O6d zDGRBW%zIx(bri!vW1fPV2IQ?o!HDeUNB@(%YE?C;cO3ZfWzM-m zzne({cu(^1z*BY&dY^Act7X8{SC`Ab{~AABYTt0~^Drca6!5hb zQ+ll&wwFY`T5}K0B$(~tpI&+^l-*bq+D$ah#7!l^HBiB;u9I#{Y$Ht5BbbF~VMuwK zE|X)Mm^RenYay+$&nejUV-T}Oe}gzB3W*_9VT3mYZW%KVp0;AsJI(WG()&R;;EwwN zzlCC*<6pD3Lf+BLbc1EDL*=DhoJm=zp{B-le?-ktSC+e?364P8dM6tAxt@ggX!#E+ z$_jxksHq$stUOSS`Pza-pVXiuJPzoMA0DT)tnQs#otVM^=F&Rm&1;*+>C&vu2=%fR zP573H^6BJ*yeLTZqBm!$)?`El6%$-5kM0I}ds@Nxg1Chav*s-k$q_BYyi`_Xs*UqY zvdf!sU)&n6#>>XRNv+` zxt0mhs%O@{tO5 zk{QOHyboL|>pcwx$q0v&P*|m@CdPOuv&Rk(S^Ar;6|kGscg3l&wZ)*WgqyB!i$5JB zV$iqF8GRZCWiHk=fF7f+6bVdQSt&wKr|72qJZ;T~!eepJnrHnGj43Sns*q5!$W3#Z zLa;9iC2@o2<=m#ERutXj7<6G}m1J_x7e59b+Ili93nPz?Q$m%GwC=loy(#bGoCqy&}TcmD*8Fo;3x7%00toF#XMh@bRC5R&R}qG*2!f6m*_!?2?zy>LP|uOZj(LVr(Gky>jQ}1I zfm~ZPk8u~{P;0sF{rTai>{($M;SXOhwqe1)StOKEd#d+tJpV>8%xrz)Kan z#>&h~I{EDe;my-2?+2-e3bKxR9Npn%t{){A8fF*z%5F9*)6L<>LMEejgcj;3sHw8i zBHc_g;07-Y6si(S)lulgLSf>EtK^`!>}PXOlCWV^EWT21ks)IT<-O`#sh^Ij;Y?LAV sr(D-)UK-PwsW#>AoN7H<3|oNgC7s|QGG3E_?cR8pvGhfKy@$X60ATL2HUIzs literal 0 HcmV?d00001 diff --git a/features/wallet/impl/src/main/res/drawable/ill_superteam_card2_120_106.webp b/features/wallet/impl/src/main/res/drawable/ill_superteam_card2_120_106.webp new file mode 100644 index 0000000000000000000000000000000000000000..f31ec2e0c311815e5fc41e9545cdb1157f3933dd GIT binary patch literal 5660 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 literal 0 HcmV?d00001 diff --git a/features/wallet/impl/src/main/res/drawable/ill_superteam_card3_120_106.webp b/features/wallet/impl/src/main/res/drawable/ill_superteam_card3_120_106.webp new file mode 100644 index 0000000000000000000000000000000000000000..25559b202d39ff491d0f9b20924d381a49896ff8 GIT binary patch literal 5920 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 Ci Date: Tue, 2 Jun 2026 14:35:09 +0300 Subject: [PATCH 3/6] Updated on 2026-08-14 --- .../response/P2PEthPoolBroadcastResponse.kt | 26 +++++-------------- .../P2PEthPoolBroadcastResultConverter.kt | 16 +++--------- .../ethpool/P2PEthPoolBroadcastResult.kt | 22 +++++----------- 3 files changed, 16 insertions(+), 48 deletions(-) diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/ethpool/models/response/P2PEthPoolBroadcastResponse.kt b/core/datasource/src/main/java/com/tangem/datasource/api/ethpool/models/response/P2PEthPoolBroadcastResponse.kt index 1970814c8c..fa07f77ec6 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/api/ethpool/models/response/P2PEthPoolBroadcastResponse.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/api/ethpool/models/response/P2PEthPoolBroadcastResponse.kt @@ -11,31 +11,19 @@ data class P2PEthPoolBroadcastResponse( @Json(name = "hash") val hash: String, @Json(name = "status") - val status: P2PEthPoolTxStatusDTO, + val status: String, @Json(name = "blockNumber") - val blockNumber: Int, + val blockNumber: Int? = null, @Json(name = "transactionIndex") - val transactionIndex: Int, + val transactionIndex: Int? = null, @Json(name = "gasUsed") - val gasUsed: String, + val gasUsed: String? = null, @Json(name = "cumulativeGasUsed") - val cumulativeGasUsed: String, + val cumulativeGasUsed: String? = null, @Json(name = "effectiveGasPrice") - val effectiveGasPrice: String?, + val effectiveGasPrice: String? = null, @Json(name = "from") val from: String, @Json(name = "to") val to: String, -) - -/** - * Transaction status from P2PEthPool API - */ -@JsonClass(generateAdapter = false) -enum class P2PEthPoolTxStatusDTO { - @Json(name = "success") - SUCCESS, - - @Json(name = "failed") - FAILED, -} \ No newline at end of file +) \ No newline at end of file diff --git a/data/staking/src/main/java/com/tangem/data/staking/converters/ethpool/P2PEthPoolBroadcastResultConverter.kt b/data/staking/src/main/java/com/tangem/data/staking/converters/ethpool/P2PEthPoolBroadcastResultConverter.kt index 13e58961c9..84fe2f7faf 100644 --- a/data/staking/src/main/java/com/tangem/data/staking/converters/ethpool/P2PEthPoolBroadcastResultConverter.kt +++ b/data/staking/src/main/java/com/tangem/data/staking/converters/ethpool/P2PEthPoolBroadcastResultConverter.kt @@ -1,11 +1,8 @@ package com.tangem.data.staking.converters.ethpool import com.tangem.datasource.api.ethpool.models.response.P2PEthPoolBroadcastResponse -import com.tangem.datasource.api.ethpool.models.response.P2PEthPoolTxStatusDTO import com.tangem.domain.staking.model.ethpool.P2PEthPoolBroadcastResult -import com.tangem.domain.staking.model.ethpool.P2PEthPoolBroadcastStatus import com.tangem.utils.converter.Converter -import java.math.BigDecimal /** * Converter from P2PEthPool Broadcast Transaction Response to Domain model @@ -15,21 +12,14 @@ internal object P2PEthPoolBroadcastResultConverter : Converter P2PEthPoolBroadcastStatus.SUCCESS - P2PEthPoolTxStatusDTO.FAILED -> P2PEthPoolBroadcastStatus.FAILED - } - } } \ No newline at end of file diff --git a/domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/ethpool/P2PEthPoolBroadcastResult.kt b/domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/ethpool/P2PEthPoolBroadcastResult.kt index 07f04f6b10..7d00699d88 100644 --- a/domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/ethpool/P2PEthPoolBroadcastResult.kt +++ b/domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/ethpool/P2PEthPoolBroadcastResult.kt @@ -1,7 +1,6 @@ package com.tangem.domain.staking.model.ethpool import com.tangem.domain.models.serialization.SerializedBigDecimal -import kotlinx.serialization.Serializable /** * P2P.org transaction broadcast result @@ -9,21 +8,12 @@ import kotlinx.serialization.Serializable */ data class P2PEthPoolBroadcastResult( val hash: String, - val status: P2PEthPoolBroadcastStatus, - val blockNumber: Int, - val transactionIndex: Int, - val gasUsed: SerializedBigDecimal, - val cumulativeGasUsed: SerializedBigDecimal, + val status: String, + val blockNumber: Int?, + val transactionIndex: Int?, + val gasUsed: SerializedBigDecimal?, + val cumulativeGasUsed: SerializedBigDecimal?, val effectiveGasPrice: SerializedBigDecimal?, val from: String, val to: String, -) - -/** - * Transaction broadcast status - */ -@Serializable -enum class P2PEthPoolBroadcastStatus { - SUCCESS, // Transaction confirmed successfully - FAILED, // Transaction failed -} \ No newline at end of file +) \ No newline at end of file From b319350dd5e225ffe7e4cc0921f3a67cee022833 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 2 Jun 2026 16:35:29 +0500 Subject: [PATCH 4/6] Updated on 2026-08-14 --- .../java/com/tangem/tap/HuaweiPushService.kt | 10 ++ .../tap/common/pushes/PushMessageHandler.kt | 42 +++++ .../pushes/TangemPushNotificationService.kt | 8 + .../common/pushes/TokenDetailsPushHandler.kt | 81 +++++++++ .../pushes/TokenDetailsPushHandlerTest.kt | 158 ++++++++++++++++++ 5 files changed, 299 insertions(+) create mode 100644 app/src/main/java/com/tangem/tap/common/pushes/PushMessageHandler.kt create mode 100644 app/src/main/java/com/tangem/tap/common/pushes/TokenDetailsPushHandler.kt create mode 100644 app/src/test/kotlin/com/tangem/tap/common/pushes/TokenDetailsPushHandlerTest.kt diff --git a/app/src/huawei/java/com/tangem/tap/HuaweiPushService.kt b/app/src/huawei/java/com/tangem/tap/HuaweiPushService.kt index cfd160dab2..83fd5c3d97 100644 --- a/app/src/huawei/java/com/tangem/tap/HuaweiPushService.kt +++ b/app/src/huawei/java/com/tangem/tap/HuaweiPushService.kt @@ -4,11 +4,18 @@ import android.os.Bundle import com.huawei.hms.push.HmsMessageService import com.huawei.hms.push.RemoteMessage import com.tangem.google.GoogleServicesHelper +import com.tangem.tap.common.pushes.PushMessageHandler import com.tangem.tap.common.pushes.PushNotificationDelegate import com.tangem.utils.logging.TangemLogger +import dagger.hilt.android.AndroidEntryPoint +import javax.inject.Inject +@AndroidEntryPoint class HuaweiPushService : HmsMessageService() { + @Inject + internal lateinit var pushMessageHandler: PushMessageHandler + private val pushNotificationDelegate: PushNotificationDelegate by lazy { PushNotificationDelegate(applicationContext) } @@ -27,6 +34,9 @@ class HuaweiPushService : HmsMessageService() { super.onMessageReceived(message) val isGoogleServicesAvailable = GoogleServicesHelper.checkGoogleServicesAvailability(this) if (isGoogleServicesAvailable) return + + message?.dataOfMap?.let(pushMessageHandler::onMessageReceived) + val notification = message?.notification ?: return val channelId = notification.channelId ?: TANGEM_CHANNEL_ID diff --git a/app/src/main/java/com/tangem/tap/common/pushes/PushMessageHandler.kt b/app/src/main/java/com/tangem/tap/common/pushes/PushMessageHandler.kt new file mode 100644 index 0000000000..d8589b644f --- /dev/null +++ b/app/src/main/java/com/tangem/tap/common/pushes/PushMessageHandler.kt @@ -0,0 +1,42 @@ +package com.tangem.tap.common.pushes + +import android.net.Uri +import androidx.core.net.toUri +import com.tangem.common.routing.DeepLinkRoute +import com.tangem.common.routing.deeplink.PayloadToDeeplinkConverter +import com.tangem.utils.extensions.uriValidate +import javax.inject.Inject + +/** + * Routes pushes received while the app is running to the matching in-app handler. + * + * Converts the push payload to a deeplink (via [PayloadToDeeplinkConverter]) and routes by its + * [host][Uri.getHost] — the same routing key [DeepLinkFactory][com.tangem.tap.routing.utils.DeepLinkFactory] uses + * for tapped deeplinks. Handlers receive the deeplink query params (not the raw payload), so both flat-key and + * `deeplink`-style payloads are handled uniformly. Each handler owns its own reaction; add a `when` branch per + * push type as new in-app reactions appear. + */ +internal class PushMessageHandler @Inject constructor( + private val tokenDetailsPushHandler: TokenDetailsPushHandler, +) { + + fun onMessageReceived(data: Map) { + val deeplink = PayloadToDeeplinkConverter.convert(data)?.toUri() ?: return + val queryParams = deeplink.getQueryParams() + when (deeplink.host) { + DeepLinkRoute.TokenDetails.host -> tokenDetailsPushHandler.handle(queryParams) + else -> Unit + } + } + + private fun Uri.getQueryParams(): Map { + val params = mutableMapOf() + queryParameterNames.forEach { name -> + val value = getQueryParameter(name) + if (name.uriValidate() && value?.uriValidate() == true) { + params[name] = value + } + } + return params + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/common/pushes/TangemPushNotificationService.kt b/app/src/main/java/com/tangem/tap/common/pushes/TangemPushNotificationService.kt index aef6c2946b..86cc8de6f0 100644 --- a/app/src/main/java/com/tangem/tap/common/pushes/TangemPushNotificationService.kt +++ b/app/src/main/java/com/tangem/tap/common/pushes/TangemPushNotificationService.kt @@ -4,11 +4,17 @@ import android.annotation.SuppressLint import com.google.firebase.messaging.FirebaseMessagingService import com.google.firebase.messaging.RemoteMessage import com.tangem.utils.logging.TangemLogger +import dagger.hilt.android.AndroidEntryPoint import io.customer.messagingpush.CustomerIOFirebaseMessagingService +import javax.inject.Inject +@AndroidEntryPoint @SuppressLint("MissingFirebaseInstanceTokenRefresh") internal class TangemPushNotificationService : FirebaseMessagingService() { + @Inject + lateinit var pushMessageHandler: PushMessageHandler + private val pushNotificationDelegate: PushNotificationDelegate by lazy { PushNotificationDelegate(applicationContext) } @@ -29,6 +35,8 @@ internal class TangemPushNotificationService : FirebaseMessagingService() { handleNotificationTrigger = false, ) + pushMessageHandler.onMessageReceived(message.data) + val notification = message.notification ?: return val channelId = notification.channelId ?: TANGEM_CHANNEL_ID diff --git a/app/src/main/java/com/tangem/tap/common/pushes/TokenDetailsPushHandler.kt b/app/src/main/java/com/tangem/tap/common/pushes/TokenDetailsPushHandler.kt new file mode 100644 index 0000000000..c370c505ce --- /dev/null +++ b/app/src/main/java/com/tangem/tap/common/pushes/TokenDetailsPushHandler.kt @@ -0,0 +1,81 @@ +package com.tangem.tap.common.pushes + +import com.tangem.common.routing.deeplink.DeeplinkConst.DERIVATION_PATH_KEY +import com.tangem.common.routing.deeplink.DeeplinkConst.NETWORK_ID_KEY +import com.tangem.common.routing.deeplink.DeeplinkConst.TOKEN_ID_KEY +import com.tangem.common.routing.deeplink.DeeplinkConst.WALLET_ID_KEY +import com.tangem.domain.account.fetcher.SingleAccountListFetcher +import com.tangem.domain.account.supplier.SingleAccountListSupplier +import com.tangem.domain.models.currency.CryptoCurrency +import com.tangem.domain.models.network.Network +import com.tangem.domain.models.wallet.UserWallet +import com.tangem.domain.models.wallet.UserWalletId +import com.tangem.domain.models.wallet.isLocked +import com.tangem.domain.models.wallet.isMultiCurrency +import com.tangem.domain.wallets.usecase.GetSelectedWalletSyncUseCase +import com.tangem.domain.wallets.usecase.GetUserWalletUseCase +import com.tangem.tap.ForegroundActivityObserver +import com.tangem.utils.coroutines.AppCoroutineScope +import com.tangem.utils.logging.TangemLogger +import kotlinx.coroutines.launch +import javax.inject.Inject + +/** + * Handles a received token-details push (same payload as + * [com.tangem.features.tokendetails.deeplink.TokenDetailsDeepLinkHandler]). + * + * When the app is open and the pushed token is not yet present in the wallet's portfolio (e.g. it was just added + * on the backend), refreshes the wallet accounts so it appears locally — the open portfolio screen then updates + * reactively via [SingleAccountListSupplier]. Does nothing else. + */ +class TokenDetailsPushHandler @Inject constructor( + private val appCoroutineScope: AppCoroutineScope, + private val getUserWalletUseCase: GetUserWalletUseCase, + private val getSelectedWalletSyncUseCase: GetSelectedWalletSyncUseCase, + private val singleAccountListSupplier: SingleAccountListSupplier, + private val singleAccountListFetcher: SingleAccountListFetcher, +) { + + fun handle(queryParams: Map) { + // Only when the app is open: a token just added on the backend should appear in the already-open portfolio. + // On cold start the fresh list is loaded by the regular auth flow instead. + if (ForegroundActivityObserver.foregroundActivity == null) return + appCoroutineScope.launch { refreshPortfolioIfTokenMissing(queryParams) } + } + + internal suspend fun refreshPortfolioIfTokenMissing(queryParams: Map) { + val networkId = queryParams[NETWORK_ID_KEY] ?: return + val tokenId = queryParams[TOKEN_ID_KEY] ?: return + val derivationPath = queryParams[DERIVATION_PATH_KEY] + + val userWallet = resolveUserWallet(queryParams[WALLET_ID_KEY]) ?: return + // Token list refresh only makes sense for an unlocked multi-currency wallet. + if (userWallet.isLocked || !userWallet.isMultiCurrency) return + + val isTokenPresent = singleAccountListSupplier.getSyncOrNull(userWallet.walletId) + ?.flattenCurrencies() + ?.any { it.matches(networkId = networkId, tokenId = tokenId, derivationPath = derivationPath) } == true + + if (isTokenPresent) return + + singleAccountListFetcher(SingleAccountListFetcher.Params(userWalletId = userWallet.walletId)) + .onLeft { TangemLogger.e("Error on refreshing portfolio from push", it) } + } + + private fun resolveUserWallet(walletId: String?): UserWallet? { + val userWalletId = walletId?.let(::UserWalletId) + return if (userWalletId != null) { + getUserWalletUseCase(userWalletId).getOrNull() + } else { + getSelectedWalletSyncUseCase().getOrNull() + } + } + + private fun CryptoCurrency.matches(networkId: String, tokenId: String, derivationPath: String?): Boolean { + val isNetwork = network.rawId.equals(networkId, ignoreCase = true) + val isCurrency = id.rawCurrencyId?.value?.equals(tokenId, ignoreCase = true) == true + val isDefaultDerivation = network.derivationPath is Network.DerivationPath.Card + val isCustomDerivation = derivationPath?.equals(network.derivationPath.value) == true + return isNetwork && isCurrency && (isDefaultDerivation || isCustomDerivation) + } +} \ No newline at end of file diff --git a/app/src/test/kotlin/com/tangem/tap/common/pushes/TokenDetailsPushHandlerTest.kt b/app/src/test/kotlin/com/tangem/tap/common/pushes/TokenDetailsPushHandlerTest.kt new file mode 100644 index 0000000000..84779067f5 --- /dev/null +++ b/app/src/test/kotlin/com/tangem/tap/common/pushes/TokenDetailsPushHandlerTest.kt @@ -0,0 +1,158 @@ +package com.tangem.tap.common.pushes + +import arrow.core.Either +import com.tangem.common.routing.deeplink.DeeplinkConst.DERIVATION_PATH_KEY +import com.tangem.common.routing.deeplink.DeeplinkConst.NETWORK_ID_KEY +import com.tangem.common.routing.deeplink.DeeplinkConst.TOKEN_ID_KEY +import com.tangem.common.routing.deeplink.DeeplinkConst.WALLET_ID_KEY +import com.tangem.domain.account.fetcher.SingleAccountListFetcher +import com.tangem.domain.account.models.AccountList +import com.tangem.domain.account.supplier.SingleAccountListSupplier +import com.tangem.domain.models.currency.CryptoCurrency +import com.tangem.domain.models.network.Network +import com.tangem.domain.models.wallet.UserWallet +import com.tangem.domain.models.wallet.UserWalletId +import com.tangem.domain.models.wallet.isLocked +import com.tangem.domain.models.wallet.isMultiCurrency +import com.tangem.domain.wallets.models.GetUserWalletError +import com.tangem.domain.wallets.usecase.GetSelectedWalletSyncUseCase +import com.tangem.domain.wallets.usecase.GetUserWalletUseCase +import com.tangem.utils.coroutines.AppCoroutineScope +import com.tangem.utils.logging.TangemLogger +import io.mockk.* +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.runTest +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test + +@OptIn(ExperimentalCoroutinesApi::class) +class TokenDetailsPushHandlerTest { + + private val getUserWalletUseCase: GetUserWalletUseCase = mockk() + private val getSelectedWalletSyncUseCase: GetSelectedWalletSyncUseCase = mockk() + private val singleAccountListSupplier: SingleAccountListSupplier = mockk() + private val singleAccountListFetcher: SingleAccountListFetcher = mockk() + + private val handler = TokenDetailsPushHandler( + appCoroutineScope = mockk(), + getUserWalletUseCase = getUserWalletUseCase, + getSelectedWalletSyncUseCase = getSelectedWalletSyncUseCase, + singleAccountListSupplier = singleAccountListSupplier, + singleAccountListFetcher = singleAccountListFetcher, + ) + + private val userWalletId = UserWalletId("011") + + @BeforeEach + fun setUp() { + mockkObject(TangemLogger) + coEvery { singleAccountListFetcher.invoke(any()) } returns Either.Right(Unit) + } + + @Test + fun `GIVEN token absent in portfolio WHEN handle push THEN refresh accounts`() = runTest { + every { getUserWalletUseCase.invoke(userWalletId) } returns Either.Right(multiCurrencyWallet()) + coEvery { singleAccountListSupplier.getSyncOrNull(userWalletId) } returns accountList(currencies = emptyList()) + + handler.refreshPortfolioIfTokenMissing(defaultData()) + + coVerify { singleAccountListFetcher.invoke(SingleAccountListFetcher.Params(userWalletId)) } + } + + @Test + fun `GIVEN token present in portfolio WHEN handle push THEN do not refresh`() = runTest { + every { getUserWalletUseCase.invoke(userWalletId) } returns Either.Right(multiCurrencyWallet()) + coEvery { + singleAccountListSupplier.getSyncOrNull(userWalletId) + } returns accountList(currencies = listOf(mockCryptoCurrency())) + + handler.refreshPortfolioIfTokenMissing(defaultData()) + + coVerify(exactly = 0) { singleAccountListFetcher.invoke(any()) } + } + + @Test + fun `GIVEN no wallet id in payload WHEN handle push THEN refresh selected wallet`() = runTest { + every { getSelectedWalletSyncUseCase.invoke() } returns Either.Right(multiCurrencyWallet()) + coEvery { singleAccountListSupplier.getSyncOrNull(userWalletId) } returns accountList(currencies = emptyList()) + + handler.refreshPortfolioIfTokenMissing(defaultData() - WALLET_ID_KEY) + + coVerify { singleAccountListFetcher.invoke(SingleAccountListFetcher.Params(userWalletId)) } + } + + @Test + fun `GIVEN no wallet id and no selected wallet WHEN handle push THEN do not refresh`() = runTest { + every { getSelectedWalletSyncUseCase.invoke() } returns Either.Left(GetUserWalletError.UserWalletNotFound) + + handler.refreshPortfolioIfTokenMissing(defaultData() - WALLET_ID_KEY) + + coVerify(exactly = 0) { singleAccountListFetcher.invoke(any()) } + } + + @Test + fun `GIVEN locked wallet WHEN handle push THEN do not refresh`() = runTest { + every { getUserWalletUseCase.invoke(userWalletId) } returns Either.Right( + value = mockk { every { isLocked } returns true }, + ) + + handler.refreshPortfolioIfTokenMissing(defaultData()) + + coVerify(exactly = 0) { singleAccountListFetcher.invoke(any()) } + } + + @Test + fun `GIVEN single currency wallet WHEN handle push THEN do not refresh`() = runTest { + every { getUserWalletUseCase.invoke(userWalletId) } returns Either.Right( + value = mockk { + every { isLocked } returns false + every { isMultiCurrency } returns false + }, + ) + + handler.refreshPortfolioIfTokenMissing(defaultData()) + + coVerify(exactly = 0) { singleAccountListFetcher.invoke(any()) } + } + + @Test + fun `GIVEN wallet not found WHEN handle push THEN do not refresh`() = runTest { + every { getUserWalletUseCase.invoke(userWalletId) } returns Either.Left( + value = GetUserWalletError.UserWalletNotFound, + ) + + handler.refreshPortfolioIfTokenMissing(defaultData()) + + coVerify(exactly = 0) { singleAccountListFetcher.invoke(any()) } + } + + private fun defaultData() = mapOf( + WALLET_ID_KEY to "011", + NETWORK_ID_KEY to "123", + TOKEN_ID_KEY to "321", + DERIVATION_PATH_KEY to "777", + ) + + private fun multiCurrencyWallet(): UserWallet = mockk { + every { isLocked } returns false + every { isMultiCurrency } returns true + every { walletId } returns userWalletId + } + + private fun accountList(currencies: List): AccountList = AccountList.empty( + userWalletId = userWalletId, + cryptoCurrencies = currencies, + ) + + private fun mockCryptoCurrency() = mockk { + every { network } returns mockk { + every { rawId } returns "123" + every { derivationPath } returns Network.DerivationPath.Card(value = "777") + } + every { id } returns CryptoCurrency.ID( + prefix = CryptoCurrency.ID.Prefix.TOKEN_PREFIX, + body = CryptoCurrency.ID.Body.NetworkIdWithDerivationPath(rawId = "321", derivationPath = "777"), + suffix = CryptoCurrency.ID.Suffix.RawID("321"), + ) + } +} \ No newline at end of file From 994186039ef3a574f5b38f6b0e577edad16a7b15 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 3 Jun 2026 21:28:38 +0500 Subject: [PATCH 5/6] Updated on 2026-08-14 --- .../CreateMobileWalletModel.kt | 1 + .../entity/CreateMobileWalletUM.kt | 1 + .../ui/CreateMobileWalletContent.kt | 36 +++++++++ .../model/MultiWalletCreateWalletModel.kt | 4 + .../ui/MultiWalletCreateWallet.kt | 76 ++++++++++++++----- .../ui/state/MultiWalletCreateWalletUM.kt | 1 + 6 files changed, 101 insertions(+), 18 deletions(-) diff --git a/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/createmobilewallet/CreateMobileWalletModel.kt b/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/createmobilewallet/CreateMobileWalletModel.kt index fb2d8cc290..3535144db7 100644 --- a/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/createmobilewallet/CreateMobileWalletModel.kt +++ b/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/createmobilewallet/CreateMobileWalletModel.kt @@ -57,6 +57,7 @@ internal class CreateMobileWalletModel @Inject constructor( onImportClick = ::onImportClick, onCreateClick = ::onCreateClick, createButtonLoading = false, + onTermsClick = { router.push(AppRoute.Disclaimer(isTosAccepted = true)) }, ), ) diff --git a/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/createmobilewallet/entity/CreateMobileWalletUM.kt b/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/createmobilewallet/entity/CreateMobileWalletUM.kt index 3746ece730..098f951a9c 100644 --- a/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/createmobilewallet/entity/CreateMobileWalletUM.kt +++ b/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/createmobilewallet/entity/CreateMobileWalletUM.kt @@ -5,4 +5,5 @@ internal data class CreateMobileWalletUM( val onBackClick: () -> Unit, val onImportClick: () -> Unit, val onCreateClick: () -> Unit, + val onTermsClick: () -> Unit, ) \ No newline at end of file diff --git a/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/createmobilewallet/ui/CreateMobileWalletContent.kt b/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/createmobilewallet/ui/CreateMobileWalletContent.kt index bf0f02e9b8..a4cfed989f 100644 --- a/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/createmobilewallet/ui/CreateMobileWalletContent.kt +++ b/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/createmobilewallet/ui/CreateMobileWalletContent.kt @@ -9,7 +9,13 @@ import androidx.compose.material3.* import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.LinkAnnotation +import androidx.compose.ui.text.SpanStyle +import androidx.compose.ui.text.TextLinkStyles +import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.text.style.TextDecoration +import androidx.compose.ui.text.withLink import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.tangem.core.ui.R @@ -19,6 +25,8 @@ import com.tangem.core.ui.components.appbar.TangemTopAppBar import com.tangem.core.ui.components.appbar.models.TopAppBarButtonUM import com.tangem.core.ui.components.feature.FeatureBlock import com.tangem.core.ui.extensions.TextReference +import com.tangem.core.ui.extensions.appendColored +import com.tangem.core.ui.extensions.appendWithStyledPlaceholder import com.tangem.core.ui.extensions.stringResourceSafe import com.tangem.core.ui.res.TangemTheme import com.tangem.core.ui.res.TangemThemePreview @@ -92,6 +100,33 @@ internal fun CreateMobileWalletContent(state: CreateMobileWalletUM, modifier: Mo iconRes = R.drawable.ic_tangem_card_24, ) } + val termsTemplate = stringResourceSafe(R.string.onboarding_create_wallet_term_of_conditions_text) + val termsLinkText = stringResourceSafe(R.string.disclaimer_title) + val termsLinkColor = TangemTheme.colors.text.accent + Text( + text = buildAnnotatedString { + appendWithStyledPlaceholder(template = termsTemplate) { + withLink( + LinkAnnotation.Clickable( + tag = "tos_link", + styles = TextLinkStyles(SpanStyle(textDecoration = TextDecoration.None)), + ) { state.onTermsClick() }, + ) { + appendColored(text = termsLinkText, color = termsLinkColor) + } + } + }, + modifier = Modifier + .fillMaxWidth() + .padding( + start = 16.dp, + top = 16.dp, + end = 16.dp, + ), + style = TangemTheme.typography.caption2, + color = TangemTheme.colors.text.tertiary, + textAlign = TextAlign.Center, + ) SecondaryButton( modifier = Modifier .fillMaxWidth() @@ -130,6 +165,7 @@ private fun PreviewCreateWalletContent() { createButtonLoading = false, onImportClick = {}, onCreateClick = {}, + onTermsClick = {}, ), ) } diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/createwallet/model/MultiWalletCreateWalletModel.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/createwallet/model/MultiWalletCreateWalletModel.kt index 365e636946..223cade12a 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/createwallet/model/MultiWalletCreateWalletModel.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/createwallet/model/MultiWalletCreateWalletModel.kt @@ -3,6 +3,7 @@ package com.tangem.features.onboarding.v2.multiwallet.impl.child.createwallet.mo import androidx.compose.runtime.Stable import com.tangem.common.CompletionResult import com.tangem.common.core.TangemSdkError +import com.tangem.common.routing.AppRoute import com.tangem.core.analytics.api.AnalyticsEventHandler import com.tangem.core.analytics.models.AnalyticsParam import com.tangem.core.analytics.models.Basic @@ -10,6 +11,7 @@ import com.tangem.core.analytics.models.event.OnboardingAnalyticsEvent import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer +import com.tangem.core.decompose.navigation.Router import com.tangem.core.ui.extensions.resourceReference import com.tangem.datasource.local.appsflyer.AppsFlyerStore import com.tangem.domain.card.repository.CardRepository @@ -39,6 +41,7 @@ import javax.inject.Inject @ModelScoped internal class MultiWalletCreateWalletModel @Inject constructor( paramsContainer: ParamsContainer, + private val router: Router, override val dispatchers: CoroutineDispatcherProvider, private val tangemSdkManager: TangemSdkManager, private val sendFeedbackEmailUseCase: SendFeedbackEmailUseCase, @@ -77,6 +80,7 @@ internal class MultiWalletCreateWalletModel @Inject constructor( onDone.emit(Step.SeedPhrase) } }, + onTermsOfUseClick = { router.push(AppRoute.Disclaimer(isTosAccepted = true)) }, dialog = null, ), ) diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/createwallet/ui/MultiWalletCreateWallet.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/createwallet/ui/MultiWalletCreateWallet.kt index d687c5ba72..079af3f1a6 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/createwallet/ui/MultiWalletCreateWallet.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/createwallet/ui/MultiWalletCreateWallet.kt @@ -8,13 +8,22 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.testTag +import androidx.compose.ui.text.LinkAnnotation +import androidx.compose.ui.text.SpanStyle +import androidx.compose.ui.text.TextLinkStyles +import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.text.style.TextDecoration +import androidx.compose.ui.text.withLink import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import com.tangem.core.ui.R as CoreUiR import com.tangem.core.ui.components.BasicDialog import com.tangem.core.ui.components.DialogButtonUM import com.tangem.core.ui.components.PrimaryButtonIconEnd import com.tangem.core.ui.components.SecondaryButton +import com.tangem.core.ui.extensions.appendColored +import com.tangem.core.ui.extensions.appendWithStyledPlaceholder import com.tangem.core.ui.extensions.resolveReference import com.tangem.core.ui.extensions.stringReference import com.tangem.core.ui.extensions.stringResourceSafe @@ -24,24 +33,10 @@ import com.tangem.core.ui.test.StoriesScreenTestTags import com.tangem.features.onboarding.v2.impl.R import com.tangem.features.onboarding.v2.multiwallet.impl.child.createwallet.ui.state.MultiWalletCreateWalletUM +@Suppress("LongMethod") @Composable internal fun MultiWalletCreateWallet(state: MultiWalletCreateWalletUM, modifier: Modifier = Modifier) { - if (state.dialog != null) { - BasicDialog( - title = state.dialog.title.resolveReference(), - message = state.dialog.message.resolveReference(), - confirmButton = DialogButtonUM( - title = state.dialog.confirmButtonText.resolveReference(), - onClick = state.dialog.onConfirmClick, - ), - dismissButton = DialogButtonUM( - title = state.dialog.dismissButtonText.resolveReference(), - isWarning = state.dialog.dismissWarningColor, - onClick = state.dialog.onDismissButtonClick, - ), - onDismissDialog = state.dialog.onDismiss, - ) - } + MultiWalletCreateWalletDialog(state) Column( modifier = modifier @@ -78,9 +73,33 @@ internal fun MultiWalletCreateWallet(state: MultiWalletCreateWalletUM, modifier: ) } + val termsTemplate = stringResourceSafe(CoreUiR.string.onboarding_create_wallet_term_of_conditions_text) + val termsLinkText = stringResourceSafe(CoreUiR.string.disclaimer_title) + val termsLinkColor = TangemTheme.colors.text.accent + Text( + text = buildAnnotatedString { + appendWithStyledPlaceholder(template = termsTemplate) { + withLink( + LinkAnnotation.Clickable( + tag = "tos_link", + styles = TextLinkStyles(SpanStyle(textDecoration = TextDecoration.None)), + ) { state.onTermsOfUseClick() }, + ) { + appendColored(text = termsLinkText, color = termsLinkColor) + } + } + }, + modifier = Modifier + .padding(start = 16.dp, end = 16.dp, bottom = 16.dp) + .fillMaxWidth(), + style = TangemTheme.typography.caption2, + color = TangemTheme.colors.text.tertiary, + textAlign = TextAlign.Center, + ) + PrimaryButtonIconEnd( modifier = Modifier - .padding(start = 16.dp, end = 16.dp, bottom = 12.dp) + .padding(start = 16.dp, end = 16.dp, bottom = 8.dp) .fillMaxWidth(), iconResId = R.drawable.ic_tangem_24, text = stringResourceSafe(R.string.onboarding_create_wallet_button_create_wallet), @@ -90,7 +109,7 @@ internal fun MultiWalletCreateWallet(state: MultiWalletCreateWalletUM, modifier: if (state.showOtherOptionsButton) { SecondaryButton( modifier = Modifier - .padding(start = 16.dp, end = 16.dp, bottom = 16.dp) + .padding(start = 16.dp, end = 16.dp, bottom = 8.dp) .fillMaxWidth(), text = stringResourceSafe(R.string.onboarding_create_wallet_options_button_options), onClick = state.onOtherOptionsClick, @@ -99,6 +118,26 @@ internal fun MultiWalletCreateWallet(state: MultiWalletCreateWalletUM, modifier: } } +@Composable +private fun MultiWalletCreateWalletDialog(state: MultiWalletCreateWalletUM) { + if (state.dialog != null) { + BasicDialog( + title = state.dialog.title.resolveReference(), + message = state.dialog.message.resolveReference(), + confirmButton = DialogButtonUM( + title = state.dialog.confirmButtonText.resolveReference(), + onClick = state.dialog.onConfirmClick, + ), + dismissButton = DialogButtonUM( + title = state.dialog.dismissButtonText.resolveReference(), + isWarning = state.dialog.dismissWarningColor, + onClick = state.dialog.onDismissButtonClick, + ), + onDismissDialog = state.dialog.onDismiss, + ) + } +} + @Preview(showBackground = true) @Composable private fun Preview() { @@ -110,6 +149,7 @@ private fun Preview() { onCreateWalletClick = {}, showOtherOptionsButton = true, onOtherOptionsClick = {}, + onTermsOfUseClick = {}, dialog = null, ), ) diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/createwallet/ui/state/MultiWalletCreateWalletUM.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/createwallet/ui/state/MultiWalletCreateWalletUM.kt index 2a6a97474f..7b2f267aaf 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/createwallet/ui/state/MultiWalletCreateWalletUM.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/createwallet/ui/state/MultiWalletCreateWalletUM.kt @@ -9,5 +9,6 @@ internal data class MultiWalletCreateWalletUM( val showOtherOptionsButton: Boolean, val onCreateWalletClick: () -> Unit, val onOtherOptionsClick: () -> Unit, + val onTermsOfUseClick: () -> Unit, val dialog: OnboardingDialogUM?, ) \ No newline at end of file From 576887dc09e897f2360f548a70873b1d83d86623 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 3 Jun 2026 16:29:11 +0000 Subject: [PATCH 6/6] Updated on 2026-08-14 --- gradle/tangem_dependencies.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/tangem_dependencies.toml b/gradle/tangem_dependencies.toml index 0ab9e14901..3a35bff319 100644 --- a/gradle/tangem_dependencies.toml +++ b/gradle/tangem_dependencies.toml @@ -5,9 +5,9 @@ # https://github.com/tangem/tangem-sdk-android/ # https://github.com/tangem/vico -tangemBlockchainSdk = "releases-5.39-1533" +tangemBlockchainSdk = "develop-1544" #tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds -tangemCardSdk = "releases-5.39-623" +tangemCardSdk = "develop-620" #tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^ tangemVico = "tangem-master-21" #tangemVico = "0.0.1" # Keep it! - used for local builds ^