Skip to content

Commit

Permalink
promo fixeds
Browse files Browse the repository at this point in the history
  • Loading branch information
polstianka committed Oct 14, 2024
1 parent 361a5ac commit ec35e30
Show file tree
Hide file tree
Showing 15 changed files with 113 additions and 20 deletions.
16 changes: 16 additions & 0 deletions apps/wallet/api/src/main/java/com/tonapps/wallet/api/API.kt
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import io.batteryapi.apis.BatteryApi
import io.batteryapi.apis.BatteryApi.UnitsGetBalance
import io.batteryapi.models.Balance
import io.batteryapi.models.Config
import io.batteryapi.models.PromoCodeBatteryPurchaseRequest
import io.batteryapi.models.RechargeMethods
import io.tonapi.infrastructure.ClientException
import io.tonapi.infrastructure.Serializer
Expand Down Expand Up @@ -504,6 +505,21 @@ class API(
}
}

fun batteryApplyPromoCode(token: String, testnet: Boolean, code: String): Boolean {
return withRetry {
battery(testnet).promoCodeBatteryPurchase(token, PromoCodeBatteryPurchaseRequest(
promoCode = code
)).success
} ?: false
}

fun batteryVerifyPurchasePromo(testnet: Boolean, code: String): Boolean {
return withRetry {
battery(testnet).verifyPurchasePromo(code)
true
} ?: false
}

fun tonconnectProof(address: String, proof: String): String {
val url = "${config.tonapiMainnetHost}/v2/wallet/auth/proof"
val data = "{\"address\":\"$address\",\"proof\":$proof}"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -352,12 +352,12 @@ class AccountRepository(
}

private fun createTonProofToken(wallet: WalletEntity): String? {
val payload = api.tonconnectPayload() ?: return null
return try {
val publicKey = wallet.publicKey
val contract = BaseWalletContract.create(publicKey, WalletVersion.V4R2.title, wallet.testnet)
val secretKey = vaultSource.getPrivateKey(publicKey) ?: throw Exception("private key not found")
val address = contract.address
val payload = api.tonconnectPayload() ?: throw Exception("payload not found")
val proof = WalletProof.signTonkeeper(
address = address,
secretKey = secretKey,
Expand Down
1 change: 1 addition & 0 deletions apps/wallet/instance/app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ dependencies {

implementation(Dependence.GooglePlay.review)
implementation(Dependence.GooglePlay.billing)
implementation(Dependence.GooglePlay.update)

implementation(Dependence.Squareup.okhttp)
implementation(Dependence.Squareup.sse)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ class Environment(context: Context) {
}

val isGooglePlayAvailable: Boolean by lazy {
// installerSource == AppInstall.Source.GOOGLE_PLAY && isGooglePlayServicesAvailable
true
installerSource == AppInstall.Source.GOOGLE_PLAY && isGooglePlayServicesAvailable
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import com.android.billingclient.api.QueryPurchasesParams
import com.android.billingclient.api.consumePurchase
import com.tonapps.extensions.MutableEffectFlow
import com.tonapps.extensions.filterList
import com.tonapps.wallet.data.account.entities.WalletEntity
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.flow.MutableStateFlow
Expand Down Expand Up @@ -108,13 +109,16 @@ class BillingManager(

suspend fun requestPurchase(
activity: Activity,
wallet: WalletEntity,
productDetails: ProductDetails
) = billingClient.ready { client ->
val productDetailsParams = BillingFlowParams.ProductDetailsParams.newBuilder()
.setProductDetails(productDetails)
.build()

val billingFlowParams = BillingFlowParams.newBuilder()
.setObfuscatedAccountId(wallet.accountId)
.setObfuscatedProfileId(wallet.accountId)
.setProductDetailsParamsList(listOf(productDetailsParams))
.build()

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package com.tonapps.tonkeeper.extensions

import android.util.Log
import com.tonapps.blockchain.ton.TONOpCode
import com.tonapps.blockchain.ton.TonTransferHelper
import com.tonapps.blockchain.ton.extensions.loadAddress
import com.tonapps.blockchain.ton.extensions.loadCoins
import com.tonapps.blockchain.ton.extensions.loadMaybeRef
import com.tonapps.blockchain.ton.extensions.loadOpCode
import com.tonapps.blockchain.ton.extensions.storeAddress
Expand Down Expand Up @@ -29,20 +32,19 @@ private fun RawMessageEntity.rebuildBodyWithCustomExcessesAccount(
TONOpCode.STONFI_SWAP -> {
builder
.storeOpCode(TONOpCode.STONFI_SWAP)
.storeAddress(slice.loadTlb(MsgAddressInt.tlbCodec()))
.storeCoins(slice.loadTlb(Coins.tlbCodec()))
.storeAddress(slice.loadTlb(MsgAddressInt.tlbCodec()))
.storeAddress(slice.loadAddress())
.storeCoins(slice.loadCoins())
.storeAddress(slice.loadAddress())

if (slice.loadBit()) {
slice.loadTlb(MsgAddressInt.tlbCodec())
slice.loadAddress()
}
slice.endParse()

builder
.storeBit(true)
.storeTlb(MsgAddressInt, excessesAddress)

builder.endCell()
.storeAddress(excessesAddress)
.endCell()
}
TONOpCode.NFT_TRANSFER -> payload
TONOpCode.JETTON_TRANSFER -> payload
Expand All @@ -60,15 +62,15 @@ private fun RawMessageEntity.rebuildJettonTransferWithCustomPayload(
}

val queryId = slice.loadUInt(64)
val jettonAmount = slice.loadTlb(Coins.tlbCodec())
val receiverAddress = slice.loadTlb(MsgAddressInt.tlbCodec())
val excessesAddress = slice.loadTlb(MsgAddressInt.tlbCodec())
val jettonAmount = slice.loadCoins()
val receiverAddress = slice.loadAddress()
val excessesAddress = slice.loadAddress()
val customPayload = slice.loadMaybeRef()
if (customPayload != null) {
return payload
}

val forwardAmount = slice.loadTlb(Coins.tlbCodec()).amount.toLong()
val forwardAmount = slice.loadCoins().amount.toLong()
val forwardBody = slice.loadMaybeRef()

return TonTransferHelper.jetton(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ class BatteryRechargeViewModel(

uiItems.addAll(uiItemsPacks(packs, selectedPackType, customAmount))

if (!api.config.batteryPromoDisable) {
if (true) { // !api.config.batteryPromoDisable
uiItems.add(Item.Space)
uiItems.add(Item.Promo(promoState))
}
Expand Down Expand Up @@ -519,8 +519,10 @@ class BatteryRechargeViewModel(
}
promoStateFlow.tryEmit(PromoState.Loading())
try {
api.battery(wallet.testnet).verifyPurchasePromo(promo)
api.batteryVerifyPurchasePromo(wallet.testnet, promo)
val token = accountRepository.requestTonProofToken(wallet) ?: throw IllegalStateException("proof token is null")
batteryRepository.setAppliedPromo(wallet.testnet, promo)
api.batteryApplyPromoCode(token, wallet.testnet, promo)
promoStateFlow.tryEmit(PromoState.Applied(promo))
} catch (_: Exception) {
batteryRepository.setAppliedPromo(wallet.testnet, null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ class BatteryRefillViewModel(
uiItems.add(uiItemBattery(batteryBalance, api.config))
uiItems.add(Item.Space)

if (!api.config.batteryPromoDisable) {
if (true) { // !api.config.batteryPromoDisable
uiItems.add(Item.Promo(promoState))
uiItems.add(Item.Space)
}
Expand Down Expand Up @@ -295,7 +295,9 @@ class BatteryRefillViewModel(
if (isInitial) {
delay(2000)
}
api.battery(wallet.testnet).verifyPurchasePromo(promo)
val token = accountRepository.requestTonProofToken(wallet) ?: throw IllegalStateException("proof token is null")
api.batteryVerifyPurchasePromo(wallet.testnet, promo)
api.batteryApplyPromoCode(token, wallet.testnet, promo)
batteryRepository.setAppliedPromo(wallet.testnet, promo)
promoStateFlow.tryEmit(PromoState.Applied(promo))
} catch (_: Exception) {
Expand Down Expand Up @@ -336,7 +338,7 @@ class BatteryRefillViewModel(

fun makePurchase(productId: String, activity: Activity) {
billingManager.productFlow(productId).collectFlow { product ->
billingManager.requestPurchase(activity, product)
billingManager.requestPurchase(activity, wallet, product)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ class PromoHolder(
private fun applyPromoCode(item: Item.Promo) {
if (inputView.text.isNotBlank() && inputView.text != item.appliedPromo && !item.isLoading) {
onSubmitPromo(inputView.text)
} else if (inputView.text.isBlank()) {
onSubmitPromo("")
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import androidx.core.app.ActivityCompat
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.updatePadding
import com.google.android.play.core.appupdate.AppUpdateManager
import com.google.android.play.core.appupdate.AppUpdateManagerFactory
import com.tonapps.extensions.toUriOrNull
import com.tonapps.tonkeeper.App
import com.tonapps.tonkeeper.deeplink.DeepLink
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ import androidx.core.content.pm.ShortcutManagerCompat
import androidx.core.net.toUri
import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.viewModelScope
import com.google.android.play.core.appupdate.AppUpdateInfo
import com.google.android.play.core.appupdate.AppUpdateManager
import com.google.android.play.core.appupdate.AppUpdateManagerFactory
import com.google.android.play.core.appupdate.AppUpdateOptions
import com.google.android.play.core.install.model.AppUpdateType
import com.google.android.play.core.install.model.UpdateAvailability
import com.google.firebase.crashlytics.FirebaseCrashlytics
import com.google.firebase.crashlytics.ktx.crashlytics
import com.google.firebase.crashlytics.setCustomKeys
Expand All @@ -22,6 +28,7 @@ import com.tonapps.extensions.locale
import com.tonapps.extensions.setLocales
import com.tonapps.extensions.toUriOrNull
import com.tonapps.ledger.ton.LedgerConnectData
import com.tonapps.tonkeeper.Environment
import com.tonapps.tonkeeper.core.AnalyticsHelper
import com.tonapps.tonkeeper.core.entities.WalletPurchaseMethodEntity
import com.tonapps.tonkeeper.core.history.HistoryHelper
Expand Down Expand Up @@ -72,6 +79,7 @@ import com.tonapps.wallet.data.settings.SettingsRepository
import com.tonapps.wallet.data.token.TokenRepository
import com.tonapps.wallet.localization.Localization
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.flow.combine
Expand All @@ -84,7 +92,9 @@ import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.take
import kotlinx.coroutines.launch
import kotlinx.coroutines.tasks.await
import kotlinx.coroutines.withContext
import uikit.extensions.activity

class RootViewModel(
app: Application,
Expand All @@ -99,11 +109,16 @@ class RootViewModel(
private val browserRepository: BrowserRepository,
private val pushManager: PushManager,
private val tokenRepository: TokenRepository,
private val environment: Environment,
savedStateHandle: SavedStateHandle,
): BaseWalletVM(app) {

private val savedState = RootModelState(savedStateHandle)

private val appUpdateManager: AppUpdateManager by lazy {
AppUpdateManagerFactory.create(context)
}

private val selectedWalletFlow: Flow<WalletEntity> = accountRepository.selectedWalletFlow

private val _hasWalletFlow = MutableEffectFlow<Boolean?>()
Expand Down Expand Up @@ -165,6 +180,35 @@ class RootViewModel(
}.filterNotNull().onEach {
settingsRepository.country = it
}.flowOn(Dispatchers.IO).launchIn(viewModelScope)


viewModelScope.launch(Dispatchers.IO) {
if (environment.isGooglePlayAvailable) {
delay(2000)
checkAppUpdate()
}
}
}

private suspend fun checkAppUpdate() = withContext(Dispatchers.IO) {
try {
val updateInfo = appUpdateManager.appUpdateInfo.await()
if (updateInfo.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE) {
startUpdateFlow(updateInfo)
}
} catch (e: Throwable) {
FirebaseCrashlytics.getInstance().recordException(e)
}
}

private suspend fun startUpdateFlow(appUpdateInfo: AppUpdateInfo) = withContext(Dispatchers.Main) {
val activity = context.activity ?: return@withContext
appUpdateManager.startUpdateFlowForResult(
appUpdateInfo,
activity,
AppUpdateOptions.defaultOptions(AppUpdateType.IMMEDIATE),
0
)
}

fun connectTonConnectBridge() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.tonapps.tonkeeper.ui.screen.swap

import android.net.Uri
import android.os.Bundle
import android.util.Log
import android.view.View
import android.view.ViewGroup
import androidx.core.view.ViewCompat
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package com.tonapps.tonkeeper.usecase.emulation

import android.util.Log
import com.tonapps.blockchain.ton.AndroidSecureRandom
import com.tonapps.blockchain.ton.extensions.EmptyPrivateKeyEd25519
import com.tonapps.blockchain.ton.extensions.base64
import com.tonapps.icu.Coins
import com.tonapps.icu.Coins.Companion.sumOf
import com.tonapps.tonkeeper.extensions.toGrams
Expand All @@ -19,6 +21,7 @@ import com.tonapps.wallet.data.settings.SettingsRepository
import io.tonapi.models.JettonQuantity
import io.tonapi.models.MessageConsequences
import io.tonapi.models.Risk
import org.ton.api.pk.PrivateKeyEd25519
import org.ton.cell.Cell
import org.ton.contract.wallet.WalletTransfer
import java.math.BigDecimal
Expand Down Expand Up @@ -56,7 +59,7 @@ class EmulationUseCase(
internalMessage: Boolean
): Cell {
return message.createSignedBody(
privateKey = EmptyPrivateKeyEd25519,
privateKey = PrivateKeyEd25519(AndroidSecureRandom),
internalMessage = internalMessage
)
}
Expand Down
1 change: 1 addition & 0 deletions buildSrc/src/main/kotlin/Dependence.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ object Dependence {
const val cronetOkhttp = "com.google.net.cronet:cronet-okhttp:0.1.0"
const val review = "com.google.android.play:review-ktx:2.0.1"
const val billing = "com.android.billingclient:billing-ktx:7.1.1"
const val update = "com.google.android.play:app-update-ktx:2.1.0"
}

object UI {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
package com.tonapps.blockchain.ton.extensions

import com.tonapps.blockchain.ton.TONOpCode
import org.ton.block.Coins
import org.ton.block.MsgAddress
import org.ton.block.MsgAddressInt
import org.ton.cell.Cell
import org.ton.cell.CellSlice
import org.ton.tlb.loadTlb

fun CellSlice.loadOpCode(): TONOpCode {
val code = loadUInt32()
Expand All @@ -15,4 +19,14 @@ fun CellSlice.loadMaybeRef(): Cell? {
return null
}
return loadRef()
}

fun CellSlice.loadAddress(): MsgAddressInt {
// loadTlb(MsgAddressInt.tlbCodec())
return loadTlb(MsgAddressInt)

}

fun CellSlice.loadCoins(): Coins {
return loadTlb(Coins)
}

0 comments on commit ec35e30

Please sign in to comment.