diff --git a/app/build.gradle.kts b/app/build.gradle.kts index e68e3543e7..81a98a6e98 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -111,6 +111,7 @@ dependencies { implementation(project(":common")) implementation(project(":core:ui")) implementation(project(":libs:crypto")) + implementation(project(":libs:auth")) /** Features */ implementation(project(":features:referral:presentation")) diff --git a/app/src/main/java/com/tangem/tap/MainActivity.kt b/app/src/main/java/com/tangem/tap/MainActivity.kt index ad1892a9a5..05e9eed54d 100644 --- a/app/src/main/java/com/tangem/tap/MainActivity.kt +++ b/app/src/main/java/com/tangem/tap/MainActivity.kt @@ -26,6 +26,7 @@ import com.tangem.tap.common.shop.GooglePayService.Companion.LOAD_PAYMENT_DATA_R import com.tangem.tap.common.shop.googlepay.GooglePayUtil.createPaymentsClient import com.tangem.tap.domain.TangemSdkManager import com.tangem.tap.features.shop.redux.ShopAction +import com.tangem.tap.proxy.AppStateHolder import com.tangem.wallet.R import com.tangem.wallet.databinding.ActivityMainBinding import dagger.hilt.android.AndroidEntryPoint @@ -33,6 +34,7 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job import java.lang.ref.WeakReference +import javax.inject.Inject import kotlin.coroutines.CoroutineContext lateinit var tangemSdk: TangemSdk @@ -51,6 +53,9 @@ val mainScope = CoroutineScope(mainCoroutineContext) @AndroidEntryPoint class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbackHolder { + @Inject + lateinit var appStateHolder: AppStateHolder + private var snackbar: Snackbar? = null private val dialogManager = DialogManager() private val intentHandler = IntentHandler() @@ -66,6 +71,7 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac tangemSdk = TangemSdk.init(this, TangemSdkManager.config) tangemSdkManager = TangemSdkManager(tangemSdk, this) + appStateHolder.tangemSdkManager = tangemSdkManager backupService = BackupService.init(tangemSdk, this) store.dispatch( diff --git a/app/src/main/java/com/tangem/tap/TapApplication.kt b/app/src/main/java/com/tangem/tap/TapApplication.kt index d5491a6088..287f2d7a1e 100644 --- a/app/src/main/java/com/tangem/tap/TapApplication.kt +++ b/app/src/main/java/com/tangem/tap/TapApplication.kt @@ -41,18 +41,16 @@ import com.tangem.tap.domain.walletconnect.WalletConnectRepository import com.tangem.tap.network.NetworkConnectivity import com.tangem.tap.persistence.CardBalanceStateAdapter import com.tangem.tap.persistence.PreferencesStorage +import com.tangem.tap.proxy.AppStateHolder import com.tangem.wallet.BuildConfig import com.zendesk.logger.Logger import dagger.hilt.android.HiltAndroidApp import org.rekotlin.Store import timber.log.Timber import zendesk.chat.Chat +import javax.inject.Inject -val store = Store( - reducer = ::appReducer, - middleware = AppState.getMiddleware(), - state = AppState(), -) +lateinit var store: Store lateinit var foregroundActivityObserver: ForegroundActivityObserver lateinit var preferencesStorage: PreferencesStorage @@ -64,9 +62,21 @@ lateinit var userTokensRepository: UserTokensRepository @HiltAndroidApp class TapApplication : Application(), ImageLoaderFactory { + @Inject + lateinit var appStateHolder: AppStateHolder + override fun onCreate() { super.onCreate() + store = Store( + reducer = { action, state -> + appReducer(action, state, appStateHolder) + }, + middleware = AppState.getMiddleware(), + state = AppState(), + ) + appStateHolder.mainStore = store + if (BuildConfig.DEBUG) { Timber.plant(Timber.DebugTree()) } @@ -91,6 +101,7 @@ class TapApplication : Application(), ImageLoaderFactory { context = this, tangemTechService = store.state.domainNetworks.tangemTechService, ) + appStateHolder.userTokensRepository = userTokensRepository } private fun initMoshiConverter() { diff --git a/app/src/main/java/com/tangem/tap/common/redux/AppReducer.kt b/app/src/main/java/com/tangem/tap/common/redux/AppReducer.kt index cbfa2565fb..a14cdb9925 100644 --- a/app/src/main/java/com/tangem/tap/common/redux/AppReducer.kt +++ b/app/src/main/java/com/tangem/tap/common/redux/AppReducer.kt @@ -14,20 +14,21 @@ import com.tangem.tap.features.send.redux.reducers.SendScreenReducer import com.tangem.tap.features.shop.redux.ShopReducer import com.tangem.tap.features.tokens.redux.TokensReducer import com.tangem.tap.features.wallet.redux.reducers.WalletReducer +import com.tangem.tap.proxy.AppStateHolder import org.rekotlin.Action -fun appReducer(action: Action, state: AppState?): AppState { +fun appReducer(action: Action, state: AppState?, appStateHolder: AppStateHolder): AppState { requireNotNull(state) if (action is AppAction.RestoreState) return action.state return AppState( navigationState = NavigationReducer.reduce(action, state), - globalState = globalReducer(action, state), + globalState = globalReducer(action, state, appStateHolder), homeState = HomeReducer.reduce(action, state), onboardingNoteState = OnboardingNoteReducer.reduce(action, state), onboardingWalletState = OnboardingWalletReducer.reduce(action, state), onboardingOtherCardsState = OnboardingOtherCardsReducer.reduce(action, state), - walletState = WalletReducer.reduce(action, state), + walletState = WalletReducer.reduce(action, state, appStateHolder), twinCardsState = TwinCardsReducer.reduce(action, state), sendState = SendScreenReducer.reduce(action, state.sendState), detailsState = DetailsReducer.reduce(action, state), diff --git a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalReducer.kt b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalReducer.kt index 8c04197c58..f8563c233a 100644 --- a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalReducer.kt +++ b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalReducer.kt @@ -5,9 +5,10 @@ import com.tangem.domain.redux.global.DomainGlobalAction import com.tangem.tap.common.redux.AppState import com.tangem.tap.features.onboarding.OnboardingManager import com.tangem.tap.preferencesStorage +import com.tangem.tap.proxy.AppStateHolder import org.rekotlin.Action -fun globalReducer(action: Action, state: AppState): GlobalState { +fun globalReducer(action: Action, state: AppState, appStateHolder: AppStateHolder): GlobalState { if (action !is GlobalAction) return state.globalState @@ -32,6 +33,7 @@ fun globalReducer(action: Action, state: AppState): GlobalState { globalState.copy(scanCardFailsCounter = 0) } is GlobalAction.SaveScanNoteResponse -> { + appStateHolder.scanResponse = action.scanResponse domainStore.dispatch(DomainGlobalAction.SaveScanNoteResponse(action.scanResponse)) globalState.copy(scanResponse = action.scanResponse) } @@ -70,7 +72,9 @@ fun globalReducer(action: Action, state: AppState): GlobalState { } is GlobalAction.SetIfCardVerifiedOnline -> globalState.copy(cardVerifiedOnline = action.verified) - is GlobalAction.FetchUserCountry.Success -> globalState.copy(userCountryCode = action.countryCode) + is GlobalAction.FetchUserCountry.Success -> globalState.copy( + userCountryCode = action.countryCode, + ) else -> globalState } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/WalletReducer.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/WalletReducer.kt index 3a180040a3..272f328df3 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/WalletReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/WalletReducer.kt @@ -30,17 +30,19 @@ import com.tangem.tap.features.wallet.redux.WalletState import com.tangem.tap.features.wallet.redux.WalletStore import com.tangem.tap.features.wallet.ui.BalanceStatus import com.tangem.tap.features.wallet.ui.BalanceWidgetData +import com.tangem.tap.proxy.AppStateHolder import org.rekotlin.Action import timber.log.Timber import java.math.BigDecimal class WalletReducer { companion object { - fun reduce(action: Action, state: AppState): WalletState = internalReduce(action, state) + fun reduce(action: Action, state: AppState, appStateHolder: AppStateHolder): WalletState = + internalReduce(action, state, appStateHolder) } } -private fun internalReduce(action: Action, state: AppState): WalletState { +private fun internalReduce(action: Action, state: AppState, appStateHolder: AppStateHolder): WalletState { val multiWalletReducer = MultiWalletReducer() val onWalletLoadedReducer = OnWalletLoadedReducer() @@ -65,17 +67,17 @@ private fun internalReduce(action: Action, state: AppState): WalletState { blockchainNetwork = BlockchainNetwork( Blockchain.Unknown, null, - emptyList() + emptyList(), ), walletsData = listOf( WalletData( currencyData = BalanceWidgetData(BalanceStatus.EmptyCard), mainButton = WalletMainButton.CreateWalletButton(true), - currency = Currency.Blockchain(Blockchain.Unknown, null) - ) - ) - ) - ) + currency = Currency.Blockchain(Blockchain.Unknown, null), + ), + ), + ), + ), ) } is WalletAction.LoadData.Failure -> { @@ -87,18 +89,18 @@ private fun internalReduce(action: Action, state: AppState): WalletState { walletsData = store.walletsData.map { it.copy( currencyData = it.currencyData.copy( - status = BalanceStatus.Unreachable - ) + status = BalanceStatus.Unreachable, + ), ) - } + }, - ) + ) } newState = newState.copy( state = ProgressState.Error, error = ErrorType.NoInternetConnection, - wallets = wallets + wallets = wallets, ) } is TapError.UnknownBlockchain -> { @@ -110,16 +112,16 @@ private fun internalReduce(action: Action, state: AppState): WalletState { blockchainNetwork = BlockchainNetwork( Blockchain.Unknown, null, - emptyList() + emptyList(), ), walletsData = listOf( WalletData( currencyData = BalanceWidgetData(BalanceStatus.UnknownBlockchain), - currency = Currency.Blockchain(Blockchain.Unknown, null) - ) - ) - ) - ) + currency = Currency.Blockchain(Blockchain.Unknown, null), + ), + ), + ), + ), ) } else -> { /* no-op */ @@ -190,7 +192,7 @@ private fun internalReduce(action: Action, state: AppState): WalletState { is WalletAction.LoadWallet.Success -> newState = onWalletLoadedReducer.reduce( wallet = action.wallet, blockchainNetwork = action.blockchain, - walletState = newState + walletState = newState, ) is WalletAction.LoadWallet.NoAccount -> { val amount = BigDecimal.ZERO @@ -209,10 +211,10 @@ private fun internalReduce(action: Action, state: AppState): WalletState { ), fiatAmount = fiatAmount, fiatAmountFormatted = fiatAmount.toFormattedFiatValue( - fiatCurrencyName = state.globalState.appCurrency.symbol + fiatCurrencyName = state.globalState.appCurrency.symbol, ), amountToCreateAccount = action.amountToCreateAccount, - ) + ), ) } val updatedWalletStore = newState.getWalletStore(action.blockchain) @@ -232,7 +234,7 @@ private fun internalReduce(action: Action, state: AppState): WalletState { val newWalletData = walletData?.copy( currencyData = walletData.currencyData.copy( status = BalanceStatus.Unreachable, - errorMessage = message + errorMessage = message, ), ) val tokenWallets = action.wallet.getTokens() @@ -244,8 +246,8 @@ private fun internalReduce(action: Action, state: AppState): WalletState { .map { it.copy( currencyData = it.currencyData.copy( - status = BalanceStatus.Unreachable, errorMessage = message - ) + status = BalanceStatus.Unreachable, errorMessage = message, + ), ) } val updatedWallets = walletStore!!.updateWallets(listOfNotNull(newWalletData) + tokenWallets).walletsData @@ -296,9 +298,9 @@ private fun internalReduce(action: Action, state: AppState): WalletState { selectedWalletData?.copy( walletAddresses = WalletAddresses( address, - walletAddresses.list - ) - ) + walletAddresses.list, + ), + ), ) } is WalletAction.SetWalletRent -> { @@ -320,6 +322,7 @@ private fun internalReduce(action: Action, state: AppState): WalletState { else -> { /* no-op */ } } + appStateHolder.walletState = newState return newState } @@ -345,7 +348,7 @@ fun Wallet.createAddressesData(): List { it.value, it.type, getShareUri(it.value), - getExploreUrl(it.value) + getExploreUrl(it.value), ) if (it.type == blockchain.defaultAddressType()) { listOfAddressData.add(0, addressData) @@ -358,27 +361,26 @@ fun Wallet.createAddressesData(): List { private fun handleCheckSignedHashesActions( action: WalletAction.Warnings, - state: WalletState + state: WalletState, ): WalletState { return when (action) { WalletAction.Warnings.CheckHashesCount.ConfirmHashesCount -> state.copy(hashesCountVerified = true) WalletAction.Warnings.CheckHashesCount.NeedToCheckHashesCountOnline -> state.copy( - hashesCountVerified = false + hashesCountVerified = false, ) is WalletAction.Warnings.Set -> state.copy(mainWarningsList = action.warningList) else -> state } } - private fun setNewFiatRate( fiatRates: Map, appCurrency: FiatCurrency, - state: WalletState + state: WalletState, ): WalletState { val rateFormatter: (BigDecimal) -> String = { rate: BigDecimal -> rate.toFiatRateString( - fiatCurrencyName = appCurrency.symbol + fiatCurrencyName = appCurrency.symbol, ) } @@ -387,7 +389,7 @@ private fun setNewFiatRate( fiatRates = fiatRates.mapNotNullValues { it.value }, rateFormatter = rateFormatter, appCurrency = appCurrency, - state = state + state = state, ) } else { setSingleWalletFiatRates( @@ -403,7 +405,7 @@ private fun setMultiWalletFiatRate( fiatRates: Map, rateFormatter: (BigDecimal) -> String, appCurrency: FiatCurrency, - state: WalletState + state: WalletState, ): WalletState { val newWalletsData = fiatRates.mapNotNull { (currency, rate) -> val walletStore = state.getWalletStore(currency) ?: return@mapNotNull null @@ -488,10 +490,9 @@ private fun setSingleWalletFiatRate( val walletData = state.primaryWallet.copy( currencyData = state.primaryWallet.currencyData.copy(fiatAmountFormatted = fiatAmount), fiatRate = rate, - fiatRateString = rateFormatted + fiatRateString = rateFormatted, ) return state.updateWalletData(walletData) - } else if (currency is Currency.Token && currency.token == token) { Timber.e("Working with token fiat rate") diff --git a/app/src/main/java/com/tangem/tap/network/auth/AuthProviderImpl.kt b/app/src/main/java/com/tangem/tap/network/auth/AuthProviderImpl.kt new file mode 100644 index 0000000000..57156ad5fa --- /dev/null +++ b/app/src/main/java/com/tangem/tap/network/auth/AuthProviderImpl.kt @@ -0,0 +1,12 @@ +package com.tangem.tap.network.auth + +import com.tangem.common.extensions.toHexString +import com.tangem.lib.auth.AuthProvider +import com.tangem.tap.proxy.AppStateHolder + +class AuthProviderImpl(private val appStateHolder: AppStateHolder) : AuthProvider { + + override fun getAuthToken(): String { + return appStateHolder.scanResponse?.card?.cardPublicKey?.toHexString() ?: "" + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/network/auth/di/AuthModule.kt b/app/src/main/java/com/tangem/tap/network/auth/di/AuthModule.kt new file mode 100644 index 0000000000..6e9eabd1f1 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/network/auth/di/AuthModule.kt @@ -0,0 +1,21 @@ +package com.tangem.tap.network.auth.di + +import com.tangem.lib.auth.AuthProvider +import com.tangem.tap.network.auth.AuthProviderImpl +import com.tangem.tap.proxy.AppStateHolder +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import javax.inject.Singleton + +@Module +@InstallIn(SingletonComponent::class) +class AuthModule { + + @Provides + @Singleton + fun provideAuthProvider(appStateHolder: AppStateHolder): AuthProvider { + return AuthProviderImpl(appStateHolder) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/proxy/AppStateHolder.kt b/app/src/main/java/com/tangem/tap/proxy/AppStateHolder.kt index eb4bfba228..c161b935fb 100644 --- a/app/src/main/java/com/tangem/tap/proxy/AppStateHolder.kt +++ b/app/src/main/java/com/tangem/tap/proxy/AppStateHolder.kt @@ -3,8 +3,8 @@ package com.tangem.tap.proxy import com.tangem.common.card.Card import com.tangem.domain.common.ScanResponse import com.tangem.tap.common.redux.AppState +import com.tangem.tap.domain.TangemSdkManager import com.tangem.tap.domain.tokens.UserTokensRepository -import com.tangem.tap.features.tokens.redux.TokensMiddleware import com.tangem.tap.features.wallet.redux.WalletState import org.rekotlin.Store @@ -14,11 +14,11 @@ import org.rekotlin.Store */ class AppStateHolder { - val scanResponse: ScanResponse? = null - val walletState: WalletState? = null - val userTokensRepository: UserTokensRepository? = null - val mainStore: Store? = null - val tokesMiddleware: TokensMiddleware? = null + var scanResponse: ScanResponse? = null + var walletState: WalletState? = null + var userTokensRepository: UserTokensRepository? = null + var mainStore: Store? = null + var tangemSdkManager: TangemSdkManager? = null fun getActualCard(): Card? { return scanResponse?.card diff --git a/app/src/main/java/com/tangem/tap/proxy/DerivationManagerImpl.kt b/app/src/main/java/com/tangem/tap/proxy/DerivationManagerImpl.kt index e27bfd5238..48396f67f1 100644 --- a/app/src/main/java/com/tangem/tap/proxy/DerivationManagerImpl.kt +++ b/app/src/main/java/com/tangem/tap/proxy/DerivationManagerImpl.kt @@ -2,12 +2,27 @@ package com.tangem.tap.proxy import com.tangem.blockchain.common.Blockchain import com.tangem.blockchain.common.Token +import com.tangem.common.CompletionResult +import com.tangem.common.card.EllipticCurve +import com.tangem.common.extensions.ByteArrayKey +import com.tangem.common.extensions.toMapKey +import com.tangem.common.hdWallet.DerivationPath +import com.tangem.domain.common.ScanResponse import com.tangem.domain.common.TapWorkarounds.derivationStyle import com.tangem.domain.common.extensions.fromNetworkId import com.tangem.lib.crypto.DerivationManager import com.tangem.lib.crypto.models.Currency import com.tangem.lib.crypto.models.NonNativeToken +import com.tangem.operations.derivation.ExtendedPublicKeysMap +import com.tangem.tap.DELAY_SDK_DIALOG_CLOSE +import com.tangem.tap.common.extensions.dispatchDebugErrorNotification +import com.tangem.tap.common.extensions.dispatchOnMain +import com.tangem.tap.common.redux.global.GlobalAction +import com.tangem.tap.domain.TapError import com.tangem.tap.domain.tokens.models.BlockchainNetwork +import com.tangem.tap.scope +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch import kotlin.coroutines.suspendCoroutine class DerivationManagerImpl( @@ -15,7 +30,6 @@ class DerivationManagerImpl( ) : DerivationManager { override suspend fun deriveMissingBlockchains(currency: Currency) = suspendCoroutine { continuation -> - val tokesMiddleware = requireNotNull(appStateHolder.tokesMiddleware) { "tokesMiddleware is null" } val blockchain = Blockchain.fromNetworkId(currency.networkId) val card = appStateHolder.getActualCard() if (blockchain != null && card != null) { @@ -31,9 +45,10 @@ class DerivationManagerImpl( blockchainNetwork, appToken, ) - if (appStateHolder.scanResponse != null) { - tokesMiddleware.deriveMissingBlockchains( - scanResponse = appStateHolder.scanResponse, + val scanResponse = appStateHolder.scanResponse + if (scanResponse != null) { + deriveMissingBlockchains( + scanResponse = scanResponse, listOf(appCurrency), ) { continuation.resumeWith(Result.success(true)) @@ -57,4 +72,99 @@ class DerivationManagerImpl( } return false } + + private fun deriveMissingBlockchains( + scanResponse: ScanResponse, + currencyList: List, + onSuccess: (ScanResponse) -> Unit, + ) { + val derivationDataList = listOfNotNull( + getDerivations(EllipticCurve.Secp256k1, scanResponse, currencyList), + getDerivations(EllipticCurve.Ed25519, scanResponse, currencyList), + ) + val derivations = derivationDataList.associate { it.derivations } + if (derivations.isEmpty()) { + onSuccess(scanResponse) + return + } + + scope.launch { + val result = appStateHolder.tangemSdkManager?.derivePublicKeys( + scanResponse.card.cardId, + derivations, + ) + when (result) { + is CompletionResult.Success -> { + val newDerivedKeys = result.data.entries + val oldDerivedKeys = scanResponse.derivedKeys + + val walletKeys = (newDerivedKeys.keys + oldDerivedKeys.keys).toSet() + + val updatedDerivedKeys = walletKeys.associateWith { walletKey -> + val oldDerivations = ExtendedPublicKeysMap(oldDerivedKeys[walletKey] ?: emptyMap()) + val newDerivations = newDerivedKeys[walletKey] ?: ExtendedPublicKeysMap(emptyMap()) + ExtendedPublicKeysMap(oldDerivations + newDerivations) + } + val updatedScanResponse = scanResponse.copy( + derivedKeys = updatedDerivedKeys, + ) + appStateHolder.mainStore?.dispatchOnMain(GlobalAction.SaveScanNoteResponse(updatedScanResponse)) + delay(DELAY_SDK_DIALOG_CLOSE) + onSuccess(updatedScanResponse) + } + is CompletionResult.Failure -> { + appStateHolder.mainStore?.dispatchDebugErrorNotification( + TapError.CustomError( + "Error adding " + + "tokens", + ), + ) + } + else -> { + throw IllegalStateException("result result is null") + } + } + } + } + + private fun getDerivations( + curve: EllipticCurve, + scanResponse: ScanResponse, + currencyList: List, + ): DerivationData? { + val wallet = scanResponse.card.wallets.firstOrNull { it.curve == curve } ?: return null + + val manageTokensCandidates = currencyList.map { it.blockchain }.distinct().filter { + it.getSupportedCurves().contains(curve) + }.mapNotNull { + it.derivationPath(scanResponse.card.derivationStyle) + } + + val customTokensCandidates = currencyList.filter { + it.blockchain.getSupportedCurves().contains(curve) + }.mapNotNull { it.derivationPath }.map { DerivationPath(it) } + + val bothCandidates = (manageTokensCandidates + customTokensCandidates).distinct() + if (bothCandidates.isEmpty()) return null + + val mapKeyOfWalletPublicKey = wallet.publicKey.toMapKey() + val alreadyDerivedKeys: ExtendedPublicKeysMap = + scanResponse.derivedKeys[mapKeyOfWalletPublicKey] ?: ExtendedPublicKeysMap(emptyMap()) + val alreadyDerivedPaths = alreadyDerivedKeys.keys.toList() + + val toDerive = bothCandidates.filterNot { alreadyDerivedPaths.contains(it) } + if (toDerive.isEmpty()) return null + + return DerivationData( + derivations = mapKeyOfWalletPublicKey to toDerive, + alreadyDerivedKeys = alreadyDerivedKeys, + mapKeyOfWalletPublicKey = mapKeyOfWalletPublicKey, + ) + } + + private class DerivationData( + val derivations: Pair>, + val alreadyDerivedKeys: ExtendedPublicKeysMap, + val mapKeyOfWalletPublicKey: ByteArrayKey, + ) } \ No newline at end of file diff --git a/core/datasource/build.gradle.kts b/core/datasource/build.gradle.kts index 7d8f651682..20d83b55e0 100644 --- a/core/datasource/build.gradle.kts +++ b/core/datasource/build.gradle.kts @@ -25,6 +25,9 @@ android { dependencies { + /** Project */ + implementation(project(":libs:auth")) + /** DI */ implementation(Library.hilt) kapt(Library.hiltKapt) diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/AuthHeaderInterceptor.kt b/core/datasource/src/main/java/com/tangem/datasource/api/AuthHeaderInterceptor.kt new file mode 100644 index 0000000000..e4d60edceb --- /dev/null +++ b/core/datasource/src/main/java/com/tangem/datasource/api/AuthHeaderInterceptor.kt @@ -0,0 +1,24 @@ +package com.tangem.datasource.api + +import com.tangem.lib.auth.AuthProvider +import okhttp3.Interceptor +import okhttp3.Response + +class AuthHeaderInterceptor( + private val authProvider: AuthProvider, +) : Interceptor { + + override fun intercept(chain: Interceptor.Chain): Response { + val request = chain.request().newBuilder().apply { + addHeader( + HEADER_CARD_KEY, authProvider.getAuthToken(), + ) + }.build() + + return chain.proceed(request) + } + + companion object { + const val HEADER_CARD_KEY = "card_public_key" + } +} \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/di/NetworkModule.kt b/core/datasource/src/main/java/com/tangem/datasource/di/NetworkModule.kt index 823d3e63d8..fd14d8802a 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/di/NetworkModule.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/di/NetworkModule.kt @@ -1,6 +1,8 @@ package com.tangem.datasource.di +import com.tangem.datasource.api.AuthHeaderInterceptor import com.tangem.datasource.api.referral.ReferralApi +import com.tangem.lib.auth.AuthProvider import dagger.Module import dagger.Provides import dagger.hilt.InstallIn @@ -30,15 +32,16 @@ class NetworkModule { @Provides @Singleton - fun provideOkHttpClient(): OkHttpClient { + fun provideOkHttpClient(authProvider: AuthProvider): OkHttpClient { return OkHttpClient.Builder() .addInterceptor( HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BASIC), ) + .addInterceptor(AuthHeaderInterceptor(authProvider)) .build() } private companion object { - const val PROD_REFERRAL_BASE_URL = "" + const val PROD_REFERRAL_BASE_URL = "https://api.tangem-tech.com/v1/" } } \ No newline at end of file diff --git a/libs/auth/.gitignore b/libs/auth/.gitignore new file mode 100644 index 0000000000..42afabfd2a --- /dev/null +++ b/libs/auth/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/libs/auth/build.gradle.kts b/libs/auth/build.gradle.kts new file mode 100644 index 0000000000..a1ea108aae --- /dev/null +++ b/libs/auth/build.gradle.kts @@ -0,0 +1,23 @@ +plugins { + id("com.android.library") + kotlin("android") +} + +android { + + defaultConfig { + compileSdk = AppConfig.compileSdkVersion + minSdk = AppConfig.minSdkVersion + targetSdk = AppConfig.targetSdkVersion + } + + kotlinOptions { + jvmTarget = JavaVersion.VERSION_1_8.toString() + } + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + isCoreLibraryDesugaringEnabled = false + } +} \ No newline at end of file diff --git a/libs/auth/src/main/AndroidManifest.xml b/libs/auth/src/main/AndroidManifest.xml new file mode 100644 index 0000000000..e314bdebe7 --- /dev/null +++ b/libs/auth/src/main/AndroidManifest.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/libs/auth/src/main/java/com/tangem/lib/auth/AuthProvider.kt b/libs/auth/src/main/java/com/tangem/lib/auth/AuthProvider.kt new file mode 100644 index 0000000000..1a3836e2d0 --- /dev/null +++ b/libs/auth/src/main/java/com/tangem/lib/auth/AuthProvider.kt @@ -0,0 +1,12 @@ +package com.tangem.lib.auth + +/** + * Provides auth for tangemTech API + */ +interface AuthProvider { + + /** + * Returns authToken for tangem tech api + */ + fun getAuthToken(): String +} \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index e6a3474eac..76949019de 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -11,6 +11,7 @@ include(":core:ui") // region Libs modules include(":libs:crypto") +include(":libs:auth") // endregion Libs modules // region Feature modules