mirror of
https://github.com/pezkuwichain/pezkuwi-wallet-android.git
synced 2026-08-04 00:15:40 +00:00
Merge b6642387ba into b616ca23d6
This commit is contained in:
@@ -181,6 +181,9 @@ dependencies {
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
implementation project(':core-db')
|
||||
implementation project(':common')
|
||||
|
||||
implementation playReview
|
||||
implementation playAppUpdate
|
||||
implementation project(':feature-splash')
|
||||
|
||||
implementation project(':feature-onboarding-api')
|
||||
|
||||
@@ -42,6 +42,7 @@ import io.novafoundation.nova.feature_dapp_api.data.repository.BrowserTabExterna
|
||||
import io.novafoundation.nova.feature_dapp_api.data.repository.DAppMetadataRepository
|
||||
import io.novafoundation.nova.feature_dapp_api.di.deeplinks.DAppDeepLinks
|
||||
import io.novafoundation.nova.feature_deep_linking.presentation.handling.PendingDeepLinkProvider
|
||||
import io.novafoundation.nova.common.appstore.AppReviewTracker
|
||||
import io.novafoundation.nova.feature_deep_linking.presentation.handling.common.DeepLinkingPreferences
|
||||
import io.novafoundation.nova.feature_gift_api.di.GiftDeepLinks
|
||||
import io.novafoundation.nova.feature_governance_api.data.MutableGovernanceState
|
||||
@@ -186,4 +187,6 @@ interface RootDependencies {
|
||||
fun chainMigrationRepository(): ChainMigrationRepository
|
||||
|
||||
fun migrationInfoRepository(): MigrationInfoRepository
|
||||
|
||||
fun appReviewTracker(): AppReviewTracker
|
||||
}
|
||||
|
||||
@@ -22,6 +22,9 @@ import io.novafoundation.nova.common.view.dialog.dialog
|
||||
import io.novafoundation.nova.feature_push_notifications.presentation.multisigsWarning.observeEnableMultisigPushesAlert
|
||||
import io.novafoundation.nova.splash.presentation.SplashBackgroundHolder
|
||||
|
||||
import io.novafoundation.nova.app.root.presentation.update.AppReviewPrompt
|
||||
import io.novafoundation.nova.app.root.presentation.update.InAppUpdates
|
||||
import io.novafoundation.nova.common.appstore.AppReviewTracker
|
||||
import javax.inject.Inject
|
||||
|
||||
class RootActivity : BaseActivity<RootViewModel, ActivityRootBinding>(), SplashBackgroundHolder {
|
||||
@@ -35,6 +38,12 @@ class RootActivity : BaseActivity<RootViewModel, ActivityRootBinding>(), SplashB
|
||||
@Inject
|
||||
lateinit var contextManager: ContextManager
|
||||
|
||||
@Inject
|
||||
lateinit var appReviewTracker: AppReviewTracker
|
||||
|
||||
private val inAppUpdates by lazy { InAppUpdates(this) }
|
||||
private val appReviewPrompt by lazy { AppReviewPrompt(this, appReviewTracker) }
|
||||
|
||||
override fun createBinding(): ActivityRootBinding {
|
||||
return ActivityRootBinding.inflate(LayoutInflater.from(this))
|
||||
}
|
||||
@@ -104,6 +113,19 @@ class RootActivity : BaseActivity<RootViewModel, ActivityRootBinding>(), SplashB
|
||||
super.onStart()
|
||||
|
||||
viewModel.noticeInForeground()
|
||||
|
||||
// Both are no-ops outside a Play install, and both swallow their own failures:
|
||||
// neither an update check nor a rating card may keep the wallet from opening.
|
||||
inAppUpdates.checkForUpdate()
|
||||
appReviewPrompt.requestIfEarned()
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
|
||||
// Finishes an immediate update that was interrupted, and installs a flexible one
|
||||
// that finished downloading while the app was in the background.
|
||||
inAppUpdates.resumeIfNeeded()
|
||||
}
|
||||
|
||||
override fun subscribe(viewModel: RootViewModel) {
|
||||
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
package io.novafoundation.nova.app.root.presentation.update
|
||||
|
||||
import android.app.Activity
|
||||
import android.util.Log
|
||||
import com.google.android.play.core.review.ReviewManagerFactory
|
||||
import io.novafoundation.nova.common.appstore.AppReviewTracker
|
||||
|
||||
/**
|
||||
* Shows Play's native rating card, in-app, when the tracker says the moment is right.
|
||||
*
|
||||
* Play decides the rest: whether the user has already rated, and whether their quota
|
||||
* allows another showing. Neither is visible to us, and neither is reported back — the
|
||||
* flow reports only that it finished, not what the user did. So there is nothing to
|
||||
* branch on afterwards, and nothing to record beyond "we spent an attempt".
|
||||
*
|
||||
* Failure is silent by design. A rating prompt that surfaces an error is worse than no
|
||||
* prompt at all.
|
||||
*/
|
||||
private const val LOG_TAG = "AppReviewPrompt"
|
||||
|
||||
class AppReviewPrompt(
|
||||
private val activity: Activity,
|
||||
private val tracker: AppReviewTracker,
|
||||
) {
|
||||
|
||||
fun requestIfEarned() {
|
||||
if (!tracker.shouldRequestReview()) return
|
||||
|
||||
runCatching {
|
||||
val manager = ReviewManagerFactory.create(activity)
|
||||
manager.requestReviewFlow()
|
||||
.addOnSuccessListener { info ->
|
||||
runCatching {
|
||||
manager.launchReviewFlow(activity, info)
|
||||
.addOnCompleteListener {
|
||||
// Completion says the flow ended, not that a review was
|
||||
// left. Record either way: the attempt is what Play counts.
|
||||
tracker.onReviewRequested()
|
||||
}
|
||||
}.onFailure { Log.w(LOG_TAG, "Could not launch review flow", it) }
|
||||
}
|
||||
.addOnFailureListener { Log.w(LOG_TAG, "Review flow unavailable", it) }
|
||||
}.onFailure { Log.w(LOG_TAG, "Review manager unavailable", it) }
|
||||
}
|
||||
}
|
||||
+109
@@ -0,0 +1,109 @@
|
||||
package io.novafoundation.nova.app.root.presentation.update
|
||||
|
||||
import android.app.Activity
|
||||
import android.util.Log
|
||||
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.InstallStatus
|
||||
import com.google.android.play.core.install.model.UpdateAvailability
|
||||
|
||||
/**
|
||||
* Tells the user a newer version exists, and installs it without leaving the app.
|
||||
*
|
||||
* There was no such mechanism before: someone on an old build stayed on it until they
|
||||
* happened to open the Play Store. For a wallet that is worse than an inconvenience —
|
||||
* a signing fix reaches nobody until they go looking for it.
|
||||
*
|
||||
* Two flows, chosen by how far behind the user is:
|
||||
*
|
||||
* - FLEXIBLE downloads in the background and keeps the wallet usable, then asks to
|
||||
* restart. This is the default, because interrupting someone mid-transfer to force
|
||||
* an update is its own kind of harm.
|
||||
* - IMMEDIATE blocks until the update is installed. Reserved for releases marked
|
||||
* high priority in Play Console, and for users who have ignored a flexible prompt
|
||||
* long enough that staleness alone justifies it.
|
||||
*
|
||||
* Only works when Play installed the app. On a Firebase or sideloaded build every call
|
||||
* here resolves to "no update available" — that is the API's design, not a failure, so
|
||||
* this must never surface an error to the user.
|
||||
*/
|
||||
private const val LOG_TAG = "InAppUpdates"
|
||||
|
||||
/** Beyond this, a flexible prompt has clearly been ignored and the update is forced. */
|
||||
private const val IMMEDIATE_AFTER_STALENESS_DAYS = 14
|
||||
|
||||
/** Play Console marks security-relevant releases at 4+; those are not optional. */
|
||||
private const val IMMEDIATE_AT_PRIORITY = 4
|
||||
|
||||
const val REQUEST_CODE_APP_UPDATE = 4711
|
||||
|
||||
class InAppUpdates(private val activity: Activity) {
|
||||
|
||||
private val manager: AppUpdateManager by lazy { AppUpdateManagerFactory.create(activity) }
|
||||
|
||||
/**
|
||||
* Ask Play whether a newer version exists and start the appropriate flow.
|
||||
*
|
||||
* Silent on every failure path: no store, no network, no Play install. A wallet
|
||||
* that cannot check for updates must still open.
|
||||
*/
|
||||
fun checkForUpdate() {
|
||||
runCatching {
|
||||
manager.appUpdateInfo
|
||||
.addOnSuccessListener { info ->
|
||||
runCatching {
|
||||
if (info.updateAvailability() != UpdateAvailability.UPDATE_AVAILABLE) return@runCatching
|
||||
|
||||
val staleness = info.clientVersionStalenessDays() ?: 0
|
||||
val forced = staleness >= IMMEDIATE_AFTER_STALENESS_DAYS ||
|
||||
info.updatePriority() >= IMMEDIATE_AT_PRIORITY
|
||||
|
||||
val type = when {
|
||||
forced && info.isUpdateTypeAllowed(AppUpdateType.IMMEDIATE) -> AppUpdateType.IMMEDIATE
|
||||
info.isUpdateTypeAllowed(AppUpdateType.FLEXIBLE) -> AppUpdateType.FLEXIBLE
|
||||
info.isUpdateTypeAllowed(AppUpdateType.IMMEDIATE) -> AppUpdateType.IMMEDIATE
|
||||
else -> return@runCatching
|
||||
}
|
||||
|
||||
manager.startUpdateFlowForResult(
|
||||
info,
|
||||
activity,
|
||||
AppUpdateOptions.newBuilder(type).build(),
|
||||
REQUEST_CODE_APP_UPDATE
|
||||
)
|
||||
}.onFailure { Log.w(LOG_TAG, "Could not start update flow", it) }
|
||||
}
|
||||
.addOnFailureListener { Log.w(LOG_TAG, "Update check failed", it) }
|
||||
}.onFailure { Log.w(LOG_TAG, "Update manager unavailable", it) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Finish an interrupted IMMEDIATE update, and install a FLEXIBLE one that finished
|
||||
* downloading while the app was backgrounded. Call from onResume.
|
||||
*
|
||||
* Without this an immediate update that was interrupted leaves the user on a screen
|
||||
* they cannot get past, and a completed flexible download never installs.
|
||||
*/
|
||||
fun resumeIfNeeded() {
|
||||
runCatching {
|
||||
manager.appUpdateInfo.addOnSuccessListener { info ->
|
||||
runCatching {
|
||||
when {
|
||||
info.updateAvailability() == UpdateAvailability.DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS -> {
|
||||
manager.startUpdateFlowForResult(
|
||||
info,
|
||||
activity,
|
||||
AppUpdateOptions.newBuilder(AppUpdateType.IMMEDIATE).build(),
|
||||
REQUEST_CODE_APP_UPDATE
|
||||
)
|
||||
}
|
||||
|
||||
info.installStatus() == InstallStatus.DOWNLOADED -> manager.completeUpdate()
|
||||
}
|
||||
}.onFailure { Log.w(LOG_TAG, "Could not resume update", it) }
|
||||
}
|
||||
}.onFailure { Log.w(LOG_TAG, "Update resume unavailable", it) }
|
||||
}
|
||||
}
|
||||
+4
-1
@@ -1,7 +1,7 @@
|
||||
buildscript {
|
||||
ext {
|
||||
// App version
|
||||
versionName = '1.1.2'
|
||||
versionName = '1.2.0'
|
||||
versionCode = 1
|
||||
|
||||
applicationId = "io.pezkuwichain.wallet"
|
||||
@@ -226,6 +226,9 @@ buildscript {
|
||||
|
||||
playIntegrity = "com.google.android.play:integrity:1.4.0"
|
||||
|
||||
playReview = "com.google.android.play:review-ktx:2.0.2"
|
||||
playAppUpdate = "com.google.android.play:app-update-ktx:2.1.0"
|
||||
|
||||
lottie = "com.airbnb.android:lottie:6.6.6"
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
package io.novafoundation.nova.common.appstore
|
||||
|
||||
import io.novafoundation.nova.common.data.storage.Preferences
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
/**
|
||||
* Decides when to ask for a Play Store review.
|
||||
*
|
||||
* Play gives no way to ask whether someone has already rated, and it throttles the
|
||||
* prompt to a handful of showings per user per year — a call made too often is
|
||||
* silently dropped. So the gates below are not there to avoid nagging, which Play
|
||||
* already handles; they are there to spend the few real chances on a good moment.
|
||||
*
|
||||
* Play policy forbids pre-qualifying ("do you like the app?"), rewarding a review, or
|
||||
* asking for a *positive* one. The prompt has to be unconditional, so the only thing
|
||||
* left to choose is when.
|
||||
*
|
||||
* Nothing here may throw. It is called from the extrinsic submission path, and a
|
||||
* rating counter must never be able to fail a transfer.
|
||||
*/
|
||||
interface AppReviewTracker {
|
||||
|
||||
/** Called after an on-chain operation or a wallet creation succeeds. */
|
||||
fun onMeaningfulSuccess()
|
||||
|
||||
/** Called when the user hits an error, which parks the prompt for a while. */
|
||||
fun onFailure()
|
||||
|
||||
/** True when every gate is satisfied. Ask Play only then. */
|
||||
fun shouldRequestReview(): Boolean
|
||||
|
||||
/** Called once the Play flow has been launched, whatever its outcome. */
|
||||
fun onReviewRequested()
|
||||
}
|
||||
|
||||
private const val KEY_SUCCESSES = "app_review_success_count"
|
||||
private const val KEY_FIRST_SEEN = "app_review_first_seen_at"
|
||||
private const val KEY_LAST_ASKED = "app_review_last_asked_at"
|
||||
private const val KEY_LAST_FAILURE = "app_review_last_failure_at"
|
||||
|
||||
/** Someone with one transfer behind them has no opinion yet. */
|
||||
private const val MIN_SUCCESSES = 3
|
||||
|
||||
/** A first-day user is judging the download, not the wallet. */
|
||||
private val MIN_AGE_MS = TimeUnit.DAYS.toMillis(3)
|
||||
|
||||
/** Play's own quota is roughly this scale; asking more often just wastes attempts. */
|
||||
private val MIN_INTERVAL_MS = TimeUnit.DAYS.toMillis(90)
|
||||
|
||||
/** Long enough that a fresh failure is no longer what the user has in mind. */
|
||||
private val FAILURE_COOLDOWN_MS = TimeUnit.DAYS.toMillis(2)
|
||||
|
||||
class RealAppReviewTracker(
|
||||
private val preferences: Preferences,
|
||||
private val currentTimeMillis: () -> Long = System::currentTimeMillis,
|
||||
) : AppReviewTracker {
|
||||
|
||||
override fun onMeaningfulSuccess() = safely {
|
||||
val now = currentTimeMillis()
|
||||
if (preferences.getLong(KEY_FIRST_SEEN, 0L) == 0L) {
|
||||
preferences.putLong(KEY_FIRST_SEEN, now)
|
||||
}
|
||||
preferences.putInt(KEY_SUCCESSES, preferences.getInt(KEY_SUCCESSES, 0) + 1)
|
||||
}
|
||||
|
||||
override fun onFailure() = safely {
|
||||
preferences.putLong(KEY_LAST_FAILURE, currentTimeMillis())
|
||||
}
|
||||
|
||||
override fun shouldRequestReview(): Boolean {
|
||||
return runCatching {
|
||||
val now = currentTimeMillis()
|
||||
|
||||
val successes = preferences.getInt(KEY_SUCCESSES, 0)
|
||||
if (successes < MIN_SUCCESSES) return@runCatching false
|
||||
|
||||
val firstSeen = preferences.getLong(KEY_FIRST_SEEN, 0L)
|
||||
if (firstSeen == 0L || now - firstSeen < MIN_AGE_MS) return@runCatching false
|
||||
|
||||
val lastAsked = preferences.getLong(KEY_LAST_ASKED, 0L)
|
||||
if (lastAsked != 0L && now - lastAsked < MIN_INTERVAL_MS) return@runCatching false
|
||||
|
||||
val lastFailure = preferences.getLong(KEY_LAST_FAILURE, 0L)
|
||||
if (lastFailure != 0L && now - lastFailure < FAILURE_COOLDOWN_MS) return@runCatching false
|
||||
|
||||
true
|
||||
}.getOrDefault(false)
|
||||
}
|
||||
|
||||
override fun onReviewRequested() = safely {
|
||||
// Written whether or not the user acted on the card: Play does not report the
|
||||
// outcome, and an attempt spends quota either way.
|
||||
preferences.putLong(KEY_LAST_ASKED, currentTimeMillis())
|
||||
}
|
||||
|
||||
private inline fun safely(block: () -> Unit) {
|
||||
runCatching(block)
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,7 @@ import io.novafoundation.nova.common.data.repository.BannerVisibilityRepository
|
||||
import io.novafoundation.nova.common.data.repository.ToggleFeatureRepository
|
||||
import io.novafoundation.nova.common.data.secrets.v1.SecretStoreV1
|
||||
import io.novafoundation.nova.common.data.secrets.v2.SecretStoreV2
|
||||
import io.novafoundation.nova.common.appstore.AppReviewTracker
|
||||
import io.novafoundation.nova.common.data.storage.Preferences
|
||||
import io.novafoundation.nova.common.data.storage.encrypt.EncryptedPreferences
|
||||
import io.novafoundation.nova.common.di.modules.Caching
|
||||
@@ -160,6 +161,8 @@ interface CommonApi {
|
||||
|
||||
fun providePreferences(): Preferences
|
||||
|
||||
fun appReviewTracker(): AppReviewTracker
|
||||
|
||||
fun backgroundAccessObserver(): BackgroundAccessObserver
|
||||
|
||||
fun provideEncryptedPreferences(): EncryptedPreferences
|
||||
|
||||
@@ -37,6 +37,8 @@ import io.novafoundation.nova.common.data.repository.ToggleFeatureRepository
|
||||
import io.novafoundation.nova.common.data.secrets.v1.SecretStoreV1
|
||||
import io.novafoundation.nova.common.data.secrets.v1.SecretStoreV1Impl
|
||||
import io.novafoundation.nova.common.data.secrets.v2.SecretStoreV2
|
||||
import io.novafoundation.nova.common.appstore.AppReviewTracker
|
||||
import io.novafoundation.nova.common.appstore.RealAppReviewTracker
|
||||
import io.novafoundation.nova.common.data.storage.Preferences
|
||||
import io.novafoundation.nova.common.data.storage.PreferencesImpl
|
||||
import io.novafoundation.nova.common.data.storage.encrypt.EncryptedPreferences
|
||||
@@ -165,6 +167,10 @@ class CommonModule {
|
||||
return PreferencesImpl(sharedPreferences)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@ApplicationScope
|
||||
fun provideAppReviewTracker(preferences: Preferences): AppReviewTracker = RealAppReviewTracker(preferences)
|
||||
|
||||
@Provides
|
||||
@ApplicationScope
|
||||
fun provideInteractionGate(): AutomaticInteractionGate = RealAutomaticInteractionGate()
|
||||
|
||||
@@ -1 +1,5 @@
|
||||
Pezkuwi Wallet — the official app for the Digital Kurdistan State. Manage your HEZ tokens, stake, and participate in on-chain governance.
|
||||
Multisig approvals work again on Pezkuwi chains. Signers could open an operation but not approve it — that is fixed.
|
||||
|
||||
The wallet now tells you when a newer version is available and installs it without leaving the app.
|
||||
|
||||
You can also rate the wallet from inside the app, after you have actually used it.
|
||||
|
||||
@@ -1 +1,5 @@
|
||||
Pezkuwi Wallet — ئەپی فەرمی دەوڵەتی دیجیتاڵی کوردستان. تۆکنەکانی HEZ بەڕێوەببە، ستەیک بکە و بەشداری بەڕێوەبردنی زنجیرە بکە.
|
||||
Pesendkirina multisig li ser zincîrên Pezkuwî dîsa dixebite. Îmzeker dikaribûn karê vekin lê pesend nekin; ev hate çareserkirin.
|
||||
|
||||
Berîk niha dema guhertoyeke nû derkeve agahdar dike û nûvekirinê bêyî derketina ji sepanê saz dike.
|
||||
|
||||
Hûn dikarin berîkê ji hundirê sepanê, piştî ku bi rastî bi kar anî, nirxînin.
|
||||
|
||||
@@ -1 +1,5 @@
|
||||
Pezkuwi Wallet — Dijital Kürdistan Devleti'nin resmi uygulaması. HEZ tokenlarınızı yönetin, stake edin ve zincir üstü yönetime katılın.
|
||||
Pezkuwi zincirlerinde multisig onayı yeniden çalışıyor. İmzacılar işlemi açabiliyor ama onaylayamıyordu; düzeltildi.
|
||||
|
||||
Cüzdan artık yeni sürüm çıktığında haber veriyor ve güncellemeyi uygulamadan çıkmadan kuruyor.
|
||||
|
||||
Cüzdanı, gerçekten kullandıktan sonra uygulama içinden puanlayabilirsiniz.
|
||||
|
||||
+8
-1
@@ -1,6 +1,7 @@
|
||||
package io.novafoundation.nova.feature_account_impl.data.extrinsic
|
||||
|
||||
import android.util.Log
|
||||
import io.novafoundation.nova.common.appstore.AppReviewTracker
|
||||
import io.novafoundation.nova.common.data.network.runtime.binding.DispatchError
|
||||
import io.novafoundation.nova.common.data.network.runtime.binding.bindDispatchError
|
||||
import io.novafoundation.nova.common.data.network.runtime.model.FeeResponse
|
||||
@@ -74,6 +75,7 @@ class RealExtrinsicService(
|
||||
private val feePaymentProviderRegistry: FeePaymentProviderRegistry,
|
||||
private val eventsRepository: EventsRepository,
|
||||
private val signingContextFactory: SigningContext.Factory,
|
||||
private val appReviewTracker: AppReviewTracker,
|
||||
private val coroutineScope: CoroutineScope? // TODO: Make it non-nullable
|
||||
) : ExtrinsicService {
|
||||
|
||||
@@ -86,8 +88,13 @@ class RealExtrinsicService(
|
||||
val (extrinsic, submissionOrigin, _, callExecutionType, signingHierarchy) = buildSubmissionExtrinsic(chain, origin, formExtrinsic, submissionOptions)
|
||||
val hash = rpcCalls.submitExtrinsic(chain.id, extrinsic)
|
||||
|
||||
// The one place every on-chain action passes through, so counting here covers
|
||||
// transfers, staking and the rest without a hook per screen. The tracker never
|
||||
// throws — a rating counter must not be able to fail a submission.
|
||||
appReviewTracker.onMeaningfulSuccess()
|
||||
|
||||
ExtrinsicSubmission(hash, submissionOrigin, callExecutionType, signingHierarchy)
|
||||
}
|
||||
}.onFailure { appReviewTracker.onFailure() }
|
||||
|
||||
override suspend fun submitMultiExtrinsicAwaitingInclusion(
|
||||
chain: Chain,
|
||||
|
||||
+4
-1
@@ -1,5 +1,6 @@
|
||||
package io.novafoundation.nova.feature_account_impl.data.extrinsic
|
||||
|
||||
import io.novafoundation.nova.common.appstore.AppReviewTracker
|
||||
import io.novafoundation.nova.feature_account_api.data.extrinsic.ExtrinsicService
|
||||
import io.novafoundation.nova.feature_account_api.data.extrinsic.ExtrinsicSplitter
|
||||
import io.novafoundation.nova.feature_account_api.data.fee.FeePaymentProviderRegistry
|
||||
@@ -21,6 +22,7 @@ class RealExtrinsicServiceFactory(
|
||||
private val eventsRepository: EventsRepository,
|
||||
private val feePaymentProviderRegistry: FeePaymentProviderRegistry,
|
||||
private val signingContextFactory: SigningContext.Factory,
|
||||
private val appReviewTracker: AppReviewTracker,
|
||||
) : ExtrinsicService.Factory {
|
||||
|
||||
override fun create(feeConfig: ExtrinsicService.FeePaymentConfig): ExtrinsicService {
|
||||
@@ -35,7 +37,8 @@ class RealExtrinsicServiceFactory(
|
||||
feePaymentProviderRegistry = registry,
|
||||
eventsRepository = eventsRepository,
|
||||
coroutineScope = feeConfig.coroutineScope,
|
||||
signingContextFactory = signingContextFactory
|
||||
signingContextFactory = signingContextFactory,
|
||||
appReviewTracker = appReviewTracker
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
+3
@@ -12,6 +12,7 @@ import io.novafoundation.nova.common.data.network.NetworkApiCreator
|
||||
import io.novafoundation.nova.common.data.network.rpc.SocketSingleRequestExecutor
|
||||
import io.novafoundation.nova.common.data.secrets.v1.SecretStoreV1
|
||||
import io.novafoundation.nova.common.data.secrets.v2.SecretStoreV2
|
||||
import io.novafoundation.nova.common.appstore.AppReviewTracker
|
||||
import io.novafoundation.nova.common.data.storage.Preferences
|
||||
import io.novafoundation.nova.common.data.storage.encrypt.EncryptedPreferences
|
||||
import io.novafoundation.nova.common.di.modules.Caching
|
||||
@@ -148,6 +149,8 @@ interface AccountFeatureDependencies {
|
||||
|
||||
fun preferences(): Preferences
|
||||
|
||||
fun appReviewTracker(): AppReviewTracker
|
||||
|
||||
fun encryptedPreferences(): EncryptedPreferences
|
||||
|
||||
fun resourceManager(): ResourceManager
|
||||
|
||||
+7
-2
@@ -4,6 +4,7 @@ import com.google.gson.Gson
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import io.novafoundation.nova.common.appstore.AppReviewTracker
|
||||
import io.novafoundation.nova.common.address.AddressIconGenerator
|
||||
import io.novafoundation.nova.common.data.mappers.mapEncryptionToCryptoType
|
||||
import io.novafoundation.nova.common.data.network.AppLinksProvider
|
||||
@@ -254,7 +255,8 @@ class AccountFeatureModule {
|
||||
extrinsicSplitter: ExtrinsicSplitter,
|
||||
feePaymentProviderRegistry: FeePaymentProviderRegistry,
|
||||
eventsRepository: EventsRepository,
|
||||
signingContextFactory: SigningContext.Factory
|
||||
signingContextFactory: SigningContext.Factory,
|
||||
appReviewTracker: AppReviewTracker,
|
||||
): ExtrinsicService.Factory = RealExtrinsicServiceFactory(
|
||||
rpcCalls,
|
||||
chainRegistry,
|
||||
@@ -264,7 +266,8 @@ class AccountFeatureModule {
|
||||
extrinsicSplitter,
|
||||
eventsRepository,
|
||||
feePaymentProviderRegistry,
|
||||
signingContextFactory
|
||||
signingContextFactory,
|
||||
appReviewTracker
|
||||
)
|
||||
|
||||
@Provides
|
||||
@@ -279,6 +282,7 @@ class AccountFeatureModule {
|
||||
feePaymentProviderRegistry: FeePaymentProviderRegistry,
|
||||
eventsRepository: EventsRepository,
|
||||
signingContextFactory: SigningContext.Factory,
|
||||
appReviewTracker: AppReviewTracker,
|
||||
): ExtrinsicService = RealExtrinsicService(
|
||||
rpcCalls,
|
||||
chainRegistry,
|
||||
@@ -289,6 +293,7 @@ class AccountFeatureModule {
|
||||
feePaymentProviderRegistry,
|
||||
eventsRepository,
|
||||
signingContextFactory,
|
||||
appReviewTracker,
|
||||
coroutineScope = null
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user