Skip to content
1 change: 1 addition & 0 deletions api/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ dependencies {

implementation(Libs.grpc_okhttp)
implementation(Libs.grpc_kotlin)
implementation(Libs.androidx_lifecycle_runtime)
implementation(Libs.androidx_room_runtime)
implementation(Libs.androidx_room_ktx)
implementation(Libs.androidx_room_rxjava3)
Expand Down
4 changes: 3 additions & 1 deletion api/src/main/java/com/getcode/db/AppDatabase.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import androidx.room.migration.Migration
import androidx.sqlite.db.SupportSQLiteDatabase
import com.getcode.model.*
import com.getcode.network.repository.decodeBase64
import com.getcode.utils.startupLog
import com.getcode.vendor.Base58
import io.reactivex.rxjava3.core.BackpressureStrategy
import io.reactivex.rxjava3.subjects.BehaviorSubject
Expand Down Expand Up @@ -72,7 +73,7 @@ object Database {
fun requireInstance() = instance!!

fun init(context: Context, entropyB64: String) {
Timber.d("init")
startupLog("database init start")
instance?.close()
val dbUniqueName = Base58.encode(entropyB64.toByteArray().subByteArray(0, 3))
dbName = "$dbNamePrefix-$dbUniqueName$dbNameSuffix"
Expand All @@ -88,6 +89,7 @@ object Database {
instance?.conversationMessageRemoteKeyDao()?.clearRemoteKeys()

isInitSubject.onNext(true)
startupLog("database init end")
}

fun close() {
Expand Down
4 changes: 4 additions & 0 deletions api/src/main/java/com/getcode/manager/MnemonicManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,9 @@ class MnemonicManager @Inject constructor(
return mnemonicPhrase.getBase64EncodedEntropy(context)
}

fun getEncodedBase58(mnemonicPhrase: MnemonicPhrase): String {
return mnemonicPhrase.getBase58EncodedEntropy(context)
}

val mnemonicCode: MnemonicCode = context.resources.let(::MnemonicCode)
}
1 change: 0 additions & 1 deletion api/src/main/java/com/getcode/manager/SessionManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ import javax.inject.Singleton
@Singleton
class SessionManager @Inject constructor(
private val client: Client,
private val tipController: TipController
) {
data class SessionState(
val entropyB64: String? = null,
Expand Down
17 changes: 14 additions & 3 deletions api/src/main/java/com/getcode/network/TipController.kt
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package com.getcode.network

import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.LifecycleOwner
import com.getcode.manager.SessionManager
import com.getcode.model.CodePayload
import com.getcode.model.TipMetadata
import com.getcode.model.PrefsBool
import com.getcode.model.PrefsString
import com.getcode.model.TipMetadata
import com.getcode.model.TwitterUser
import com.getcode.network.client.Client
import com.getcode.network.client.fetchTwitterUser
Expand Down Expand Up @@ -38,7 +41,7 @@ typealias TipUser = Pair<String, CodePayload>
class TipController @Inject constructor(
private val client: Client,
private val prefRepository: PrefRepository,
) {
): LifecycleEventObserver {

private var pollTimer: Timer? = null
private var lastPoll: Long = 0L
Expand Down Expand Up @@ -139,7 +142,15 @@ class TipController @Inject constructor(
prefRepository.set(PrefsBool.SEEN_TIP_CARD, true)
}

fun stopTimer() {
private fun stopTimer() {
pollTimer?.cancel()
}

override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
when (event) {
Lifecycle.Event.ON_RESUME -> checkForConnection()
Lifecycle.Event.ON_STOP -> stopTimer()
else -> Unit
}
}
}
34 changes: 14 additions & 20 deletions api/src/main/java/com/getcode/network/client/Client.kt
Original file line number Diff line number Diff line change
@@ -1,25 +1,27 @@
package com.getcode.network.client

import android.content.Context
import com.getcode.analytics.AnalyticsService
import com.getcode.manager.MnemonicManager
import com.getcode.manager.SessionManager
import com.getcode.network.BalanceController
import com.getcode.network.HistoryController
import com.getcode.network.exchange.Exchange
import com.getcode.network.repository.AccountRepository
import com.getcode.network.repository.IdentityRepository
import com.getcode.network.repository.MessagingRepository
import com.getcode.network.repository.PrefRepository
import com.getcode.network.repository.TransactionRepository
import com.getcode.utils.network.NetworkConnectivityListener
import com.getcode.network.service.ChatService
import com.getcode.network.service.DeviceService
import com.getcode.utils.ErrorUtils
import dagger.hilt.android.qualifiers.ApplicationContext
import com.getcode.utils.network.NetworkConnectivityListener
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.cancel
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import timber.log.Timber
import java.util.Timer
Expand All @@ -31,8 +33,6 @@ internal const val TAG = "Client"

@Singleton
class Client @Inject constructor(
@ApplicationContext
internal val context: Context,
internal val identityRepository: IdentityRepository,
internal val transactionRepository: TransactionRepository,
internal val messagingRepository: MessagingRepository,
Expand All @@ -46,9 +46,9 @@ class Client @Inject constructor(
internal val networkObserver: NetworkConnectivityListener,
internal val chatService: ChatService,
internal val deviceService: DeviceService,
internal val mnemonicManager: MnemonicManager,
) {

private val TAG = "PollTimer"
private val scope = CoroutineScope(Dispatchers.IO)

private var pollTimer: Timer? = null
Expand All @@ -57,13 +57,15 @@ class Client @Inject constructor(
private fun startPollTimerWhenAuthenticated() {
Timber.tag(TAG).i("Creating poll timer")
scope.launch {
SessionManager.authState.collect {
if (it.isAuthenticated == true) {
SessionManager.authState
.map { it.isAuthenticated }
.filterNotNull()
.filter { it }
.onEach {
Timber.tag(TAG).i("User Authenticated - starting timer")
startPollTimer()
this.cancel()
}
}
}.launchIn(this)
}
}

Expand Down Expand Up @@ -100,14 +102,6 @@ class Client @Inject constructor(
startPollTimerWhenAuthenticated()
}

fun pollOnce(delay: Long = 2_000L) {
scope.launch {
delay(delay)
Timber.tag(TAG).i("Poll Once")
poll()
}
}

fun stopTimer() {
Timber.tag(TAG).i("Cancelling Poller")
pollTimer?.cancel()
Expand Down
8 changes: 4 additions & 4 deletions api/src/main/java/com/getcode/network/client/Client_Chat.kt
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,15 @@ suspend fun Client.setSubscriptionState(owner: KeyPair, chatId: ID, subscribed:

suspend fun Client.fetchMessagesFor(owner: KeyPair, chat: Chat, cursor: Cursor? = null, limit: Int? = null) : Result<List<ChatMessage>> {
return chatService.fetchMessagesFor(owner, chat.id, cursor, limit)
.map {
.mapCatching {
val domain = if (chat.title is Title.Domain) {
Domain.from(chat.title.value)
} else {
null
} ?: return@map it
} ?: return@mapCatching it

val organizer = SessionManager.getOrganizer() ?: return@map it
val relationship = organizer.relationshipFor(domain) ?: return@map it
val organizer = SessionManager.getOrganizer() ?: return@mapCatching it
val relationship = organizer.relationshipFor(domain) ?: return@mapCatching it

val hasEncryptedContent = it.firstOrNull { it.hasEncryptedContent } != null
if (hasEncryptedContent) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ fun Client.transferWithResultSingle(
return getTransferPreflightAction(amount.kin)
.andThen(Single.defer {
transactionRepository.transfer(
context, amount, fee, additionalFees, organizer, rendezvousKey, destination, isWithdrawal, tipMetadata
amount, fee, additionalFees, organizer, rendezvousKey, destination, isWithdrawal, tipMetadata
)
})
.map {
Expand Down Expand Up @@ -141,7 +141,6 @@ fun Client.sendRemotely(
getTransferPreflightAction(truncatedAmount.kin)
.andThen(
sendRemotely(
context = context,
amount = truncatedAmount,
organizer = organizer,
rendezvousKey = rendezvousKey,
Expand All @@ -150,7 +149,7 @@ fun Client.sendRemotely(
.doOnComplete {
val giftCardItem = GiftCard(
key = giftCard.cluster.vaultPublicKey.base58(),
entropy = giftCard.mnemonicPhrase.getBase58EncodedEntropy(context),
entropy = mnemonicManager.getEncodedBase58(giftCard.mnemonicPhrase),
amount = truncatedAmount.kin.quarks,
date = System.currentTimeMillis()
)
Expand Down Expand Up @@ -367,15 +366,14 @@ private fun Client.withdraw(
}

fun Client.sendRemotely(
context: Context,
amount: KinAmount,
organizer: Organizer,
rendezvousKey: PublicKey,
giftCard: GiftCardAccount
): Completable {
return Completable.defer {
transactionRepository.sendRemotely(
context, amount, organizer, rendezvousKey, giftCard
amount, organizer, rendezvousKey, giftCard
)
.map {
if (it is IntentRemoteSend) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,6 @@ class TransactionRepository @Inject constructor(
}

fun transfer(
context: Context,
amount: KinAmount,
fee: Kin,
additionalFees: List<Fee>,
Expand Down Expand Up @@ -254,7 +253,6 @@ class TransactionRepository @Inject constructor(
}

fun sendRemotely(
context: Context,
amount: KinAmount,
organizer: Organizer,
rendezvousKey: PublicKey,
Expand Down
23 changes: 23 additions & 0 deletions api/src/main/java/com/getcode/utils/Logging.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.getcode.utils

import com.bugsnag.android.Bugsnag
import timber.log.Timber


fun startupLog(message: String, error: Throwable? = null) {
val tag = "app-startup"

Timber.tag(tag).let {
if (error != null) {
it.e(error, message)
} else {
it.d(message)
}
}

if (Bugsnag.isStarted()) {
Bugsnag.leaveBreadcrumb("$tag | $message")
}

error?.let(ErrorUtils::handleError)
}
2 changes: 2 additions & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ android {
buildToolsVersion = Android.buildToolsVersion
testInstrumentationRunner = Android.testInstrumentationRunner

resValue("string", "applicationId", Android.namespace)

buildConfigField("String", "MIXPANEL_API_KEY", "\"${tryReadProperty(rootProject.rootDir, "MIXPANEL_API_KEY")}\"")
buildConfigField("String", "KADO_API_KEY", "\"${tryReadProperty(rootProject.rootDir, "KADO_API_KEY")}\"")
buildConfigField("Boolean", "NOTIFY_ERRORS", "false")
Expand Down
6 changes: 4 additions & 2 deletions app/src/main/java/com/getcode/App.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import com.bugsnag.android.Bugsnag
import com.getcode.manager.AuthManager
import com.getcode.network.integrity.DeviceCheck
import com.getcode.utils.ErrorUtils
import com.getcode.utils.startupLog
import com.getcode.view.main.bill.CashBillAssets
import com.google.firebase.Firebase
import com.google.firebase.initialize
Expand All @@ -22,12 +23,12 @@ class App : Application() {

override fun onCreate() {
super.onCreate()

println("app-startup onCreate start")
CashBillAssets.load(this)

Firebase.initialize(this)
DeviceCheck.register(this)
authManager.init(this)
authManager.init()

AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)

Expand Down Expand Up @@ -61,5 +62,6 @@ class App : Application() {
} else {
Bugsnag.start(this)
}
startupLog("app onCreate end")
}
}
Loading