Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions api/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ dependencies {
implementation(Libs.rxjava)
implementation(Libs.kotlinx_coroutines_core)
implementation(Libs.kotlinx_serialization_json)
implementation(Libs.kotlinx_datetime)
implementation(Libs.inject)

implementation(Libs.grpc_okhttp)
Expand Down
7 changes: 5 additions & 2 deletions api/src/main/java/com/getcode/model/Kin.kt
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,13 @@ data class Kin(val quarks: Long): Value {
}
}

fun min(a: Kin, b: Kin): Kin {
private fun min(a: Kin, b: Kin): Kin {
if (a.quarks > b.quarks) {
return b
}

return a
}
}

val Kin.description: String
get() = "K ${toKinTruncating().quarks} ${fractionalQuarks()}"
28 changes: 21 additions & 7 deletions api/src/main/java/com/getcode/network/client/Client_Transaction.kt
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ import com.getcode.solana.keys.base58
import com.getcode.solana.organizer.GiftCardAccount
import com.getcode.solana.organizer.Organizer
import com.getcode.solana.organizer.Relationship
import com.getcode.utils.TraceType
import com.getcode.utils.flowInterval
import com.getcode.utils.trace
import io.reactivex.rxjava3.core.Completable
import io.reactivex.rxjava3.core.Single
import io.reactivex.rxjava3.schedulers.Schedulers
Expand Down Expand Up @@ -337,15 +339,20 @@ fun Client.withdrawExternally(
Completable.complete()
}.doOnComplete {
Timber.d(steps.joinToString("\n"))
}
}.concatWith(
// 6. Execute withdrawal
.concatWith(
withdraw(
amount = amount,
organizer = organizer,
destination = destination
)
withdraw(
amount = amount,
organizer = organizer,
destination = destination
)
).doOnComplete {
trace(
tag = "Trx",
message = "Withdraw completed",
type = TraceType.Process
)
}
}

private fun Client.withdraw(
Expand Down Expand Up @@ -517,6 +524,13 @@ fun Client.receiveFromPrimaryIfWithinLimits(organizer: Organizer): Completable {
}
}
.ignoreElement()
.andThen {
trace(
tag = "Trx",
message = "Received from primary",
type = TraceType.Process
)
}
.andThen { fetchLimits(true) }
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,24 @@ class TransactionReceiver @Inject constructor(
organizer = organizer
).blockingGet()

trace(
tag = "Trx",
message = "Received from relationship",
type = TraceType.Process,
metadata = {
"domain" to relationship.domain.relationshipHost
"kin" to relationship.partialBalance
}
)

receivedTotal += relationship.partialBalance

trace(
tag = "Trx",
message = "Received from incoming",
type = TraceType.Process
)

if (intent is IntentPublicTransfer) {
setTray(organizer, intent.resultTray)
}
Expand Down
10 changes: 10 additions & 0 deletions api/src/main/java/com/getcode/network/exchange/Exchange.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import com.getcode.network.core.NetworkOracle
import com.getcode.network.repository.PrefRepository
import com.getcode.utils.ErrorUtils
import com.getcode.utils.TraceType
import com.getcode.utils.format
import com.getcode.utils.trace
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
Expand All @@ -23,6 +24,7 @@ import kotlinx.coroutines.flow.mapNotNull
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.datetime.Instant
import timber.log.Timber
import java.util.Date
import javax.inject.Inject
Expand Down Expand Up @@ -249,6 +251,14 @@ class CodeExchange @Inject constructor(
rates.rateForUsd()!!
}

trace(tag = "Background",
message = "Updated rates",
type = TraceType.Process,
metadata = {
"date" to Instant.fromEpochMilliseconds(rates.dateMillis).format("yyyy-MM-dd HH:mm:ss")
}
)

}

@OptIn(ExperimentalTime::class)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -584,6 +584,17 @@ class TransactionRepository @Inject constructor(
.doOnSuccess {
setLimits(it)
setMaximumDeposit(it.maxDeposit)
trace(
tag = "Trx",
message = "Fetched limits",
type = TraceType.Process,
metadata = {
val sendLimit = it.sendLimitFor(CurrencyCode.USD)
if (sendLimit != null) {
"limitNextTx" to sendLimit
}
}
)
}
.doOnError(ErrorUtils::handleError)
.toFlowable()
Expand Down
11 changes: 11 additions & 0 deletions api/src/main/java/com/getcode/solana/organizer/Organizer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ import com.getcode.model.Kin
import com.getcode.model.unusable
import com.getcode.network.repository.getPublicKeyBase58
import com.getcode.solana.keys.*
import com.getcode.utils.TraceType
import com.getcode.utils.timedTrace
import com.getcode.utils.trace
import timber.log.Timber

class Organizer(
Expand Down Expand Up @@ -59,6 +61,15 @@ class Organizer(
this.accountInfos = infos
tray.createRelationships(infos)
propagateBalances()

trace(
tag = "Organizer",
message = "Fetched account infos",
type = TraceType.Process,
metadata = {
"tray" to tray.reportableRepresentation()
}
)
}

fun getAccountInfo() = accountInfos
Expand Down
28 changes: 26 additions & 2 deletions api/src/main/java/com/getcode/solana/organizer/Tray.kt
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
package com.getcode.solana.organizer

import android.content.Context
import com.getcode.crypt.DerivePath
import com.getcode.crypt.DerivedKey
import com.getcode.crypt.MnemonicPhrase
import com.getcode.model.AccountInfo
import com.getcode.model.Domain
import com.getcode.model.Kin
import com.getcode.model.RelationshipBox
import com.getcode.model.description
import com.getcode.solana.keys.PublicKey
import com.getcode.solana.keys.base58
import com.getcode.utils.TraceType
import com.getcode.utils.timedTrace
import com.getcode.utils.padded
import com.getcode.utils.trace
import kotlin.math.min

Expand Down Expand Up @@ -866,6 +867,29 @@ class Tray(
return container
}

fun reportableRepresentation(): List<String> {
return listOf(
string(named = "Primary ", partialAccount = owner),
string(named = "Incoming ", partialAccount = incoming),
string(named = "Outgoing ", partialAccount = outgoing),
string("1 ", slot = slot(SlotType.Bucket1)),
string("10 ", slot = slot(SlotType.Bucket10)),
string("100 ", slot = slot(SlotType.Bucket100)),
string("1k ", slot = slot(SlotType.Bucket1k)),
string("10k ", slot = slot(SlotType.Bucket10k)),
string("100k ", slot = slot(SlotType.Bucket100k)),
string("1m ", slot = slot(SlotType.Bucket1m)),
)
}

private fun string(named: String, partialAccount: PartialAccount): String {
return "$named ${partialAccount.getCluster().vaultPublicKey.base58().padded(44)}) ${partialAccount.partialBalance.description}"
}

private fun string(named: String, slot: Slot): String {
return "$named ${slot.getCluster().vaultPublicKey.base58().padded(44)}) ${slot.partialBalance.description}"
}

override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.getcode.util
package com.getcode.utils

import kotlinx.datetime.DatePeriod
import kotlinx.datetime.DateTimeUnit
Expand All @@ -9,6 +9,9 @@ import kotlinx.datetime.atStartOfDayIn
import kotlinx.datetime.minus
import kotlinx.datetime.plus
import kotlinx.datetime.toLocalDateTime
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale

fun Instant.toLocalDate(timeZone: TimeZone = TimeZone.currentSystemDefault()) =
toLocalDateTime(timeZone).date
Expand All @@ -18,4 +21,13 @@ fun LocalDate.atStartOfDay(tz: TimeZone = TimeZone.currentSystemDefault()) = atS
fun LocalDate.atEndOfDay(tz: TimeZone = TimeZone.currentSystemDefault()): Instant {
val tomorrowAtMidnight = ((this + DatePeriod(days = 1)).atStartOfDayIn(tz))
return tomorrowAtMidnight.minus(value = 1, unit = DateTimeUnit.NANOSECOND)
}

fun Instant.format(format: String = "yyyy-MM-dd"): String {
val epoch = this.toEpochMilliseconds()

val formatter = SimpleDateFormat(format, Locale.getDefault())
val date = Date(epoch)

return formatter.format(date)
}
34 changes: 27 additions & 7 deletions api/src/main/java/com/getcode/utils/Logging.kt
Original file line number Diff line number Diff line change
Expand Up @@ -67,25 +67,28 @@ fun trace(
message: String,
tag: String? = null,
type: TraceType = TraceType.Log,
metadata: MetadataBuilder.() -> Unit = {},
error: Throwable? = null
) {
val tree = if (tag == null) Timber else Timber.tag(tag)
val traceMessage = if (tag == null) message else "trace : $message"
val tagBlock = tag?.let { "[$it] " }
val tree = if (tagBlock == null) Timber else Timber.tag(tagBlock)

tree.d(traceMessage)
tree.d(message)

val metadataMap = metadata { metadata() }

if (Bugsnag.isStarted()) {
val breadcrumb = if (tag != null) {
"$tag | $traceMessage"
"$tagBlock $message"
} else {
traceMessage
message
}

val breadcrumbType = type.toBugsnagBreadcrumbType()
if (breadcrumbType != null) {
Bugsnag.leaveBreadcrumb(
breadcrumb,
emptyMap(),
metadataMap,
breadcrumbType
)
}
Expand All @@ -98,6 +101,7 @@ fun <T> timedTrace(
message: String,
tag: String? = null,
type: TraceType = TraceType.Log,
metadata: MetadataBuilder.() -> Unit = {},
error: Throwable? = null,
block: () -> T
): T {
Expand All @@ -107,7 +111,23 @@ fun <T> timedTrace(
}

val newMessage = "$message took ${time.inWholeMilliseconds}ms"
trace(newMessage, tag, type, error)
trace(newMessage, tag, type, metadata, error)

return result
}

class MetadataBuilder {
private val map = mutableMapOf<String, Any>()

infix fun String.to(value: Any) {
map[this] = value
}

fun build(): Map<String, Any> = map
}

fun metadata(block: MetadataBuilder.() -> Unit): Map<String, Any> {
val builder = MetadataBuilder()
builder.block()
return builder.build()
}
10 changes: 10 additions & 0 deletions api/src/main/java/com/getcode/utils/String.kt
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,15 @@ fun String.base64EncodedData(): ByteArray {
return data
}

fun String.padded(minCount: Int): String {
return if (this.length < minCount) {
val toInsert = minCount - this.length
val padding = " ".repeat(toInsert)
this + padding
} else {
this
}
}

typealias Base64String = String
typealias Base58String = String
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ import com.getcode.util.CurrencyUtils
import com.getcode.util.resources.ResourceHelper
import com.getcode.util.resources.ResourceType
import com.getcode.utils.ErrorUtils
import com.getcode.utils.TraceType
import com.getcode.utils.installationId
import com.getcode.utils.trace
import com.getcode.view.MainActivity
import com.google.firebase.Firebase
import com.google.firebase.installations.installations
Expand Down Expand Up @@ -189,6 +191,15 @@ class CodePushMessagingService : FirebaseMessagingService(),
.setContentIntent(buildContentIntent(type))

notificationManager.notify(title.hashCode(), notificationBuilder.build())

trace(
tag = "Push",
message = "Push notification shown",
metadata = {
"category" to type.name
},
type = TraceType.Process
)
}

private fun updateOrganizerAndSwap() = launch {
Expand Down
8 changes: 8 additions & 0 deletions app/src/main/java/com/getcode/util/AccountUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,14 @@ object AccountUtils {
} else {
currentAttempt++
if (currentAttempt < maxRetries) {
trace(
tag = "Account",
message = "Retrying login",
metadata = {
"count" to currentAttempt
},
type = TraceType.Process,
)
trace("Retrying after ${delayDuration.inWholeMilliseconds} ms...", type = TraceType.Log)
delay(delayDuration.inWholeMilliseconds)
}
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/java/com/getcode/util/DateUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import android.text.format.DateFormat
import android.text.format.DateUtils
import androidx.compose.runtime.Composable
import androidx.compose.ui.platform.LocalContext
import com.getcode.utils.atStartOfDay
import com.getcode.utils.toLocalDate
import kotlinx.datetime.Clock
import kotlinx.datetime.Instant
import java.util.Calendar
Expand Down
Loading