Moves cashu processing to a state class to account for errors.

This commit is contained in:
Vitor Pamplona 2023-06-26 20:17:35 -04:00
parent 9bed6fdb9a
commit 833e6bc3e1
3 changed files with 42 additions and 18 deletions

View File

@ -6,6 +6,7 @@ import com.google.gson.JsonArray
import com.google.gson.JsonObject import com.google.gson.JsonObject
import com.google.gson.JsonParser import com.google.gson.JsonParser
import com.vitorpamplona.amethyst.service.lnurl.LightningAddressResolver import com.vitorpamplona.amethyst.service.lnurl.LightningAddressResolver
import com.vitorpamplona.amethyst.ui.components.GenericLoadable
import okhttp3.MediaType.Companion.toMediaType import okhttp3.MediaType.Companion.toMediaType
import okhttp3.Request import okhttp3.Request
import okhttp3.RequestBody.Companion.toRequestBody import okhttp3.RequestBody.Companion.toRequestBody
@ -21,21 +22,25 @@ data class CashuToken(
) )
class CashuProcessor { class CashuProcessor {
fun parse(cashutoken: String): CashuToken { fun parse(cashuToken: String): GenericLoadable<CashuToken> {
val base64token = cashutoken.replace("cashuA", "") try {
val cashu = JsonParser.parseString(String(Base64.getDecoder().decode(base64token))) val base64token = cashuToken.replace("cashuA", "")
val token = cashu.asJsonObject.get("token").asJsonArray[0].asJsonObject val cashu = JsonParser.parseString(String(Base64.getDecoder().decode(base64token)))
val proofs = token["proofs"].asJsonArray val token = cashu.asJsonObject.get("token").asJsonArray[0].asJsonObject
val mint = token["mint"].asString val proofs = token["proofs"].asJsonArray
val mint = token["mint"].asString
var totalAmount = 0L var totalAmount = 0L
for (proof in proofs) { for (proof in proofs) {
totalAmount += proof.asJsonObject["amount"].asLong totalAmount += proof.asJsonObject["amount"].asLong
}
val fees = Math.max(((totalAmount * 0.02).toInt()), 2)
val redeemInvoiceAmount = totalAmount - fees
return GenericLoadable.Loaded(CashuToken(mint, totalAmount, fees, redeemInvoiceAmount, proofs))
} catch (e: Exception) {
return GenericLoadable.Error<CashuToken>("Could not parse this cashu token")
} }
val fees = Math.max(((totalAmount * 0.02).toInt()), 2)
val redeemInvoiceAmount = totalAmount - fees
return CashuToken(mint, totalAmount, fees, redeemInvoiceAmount, proofs)
} }
fun melt(token: CashuToken, lud16: String, onSuccess: (String) -> Unit, onError: (String) -> Unit) { fun melt(token: CashuToken, lud16: String, onSuccess: (String) -> Unit, onError: (String) -> Unit) {

View File

@ -35,7 +35,7 @@ import kotlinx.coroutines.launch
@Composable @Composable
fun CashuPreview(cashutoken: String, accountViewModel: AccountViewModel) { fun CashuPreview(cashutoken: String, accountViewModel: AccountViewModel) {
var cachuData by remember { mutableStateOf<CashuToken?>(null) } var cachuData by remember { mutableStateOf<GenericLoadable<CashuToken>>(GenericLoadable.Loading<CashuToken>()) }
LaunchedEffect(key1 = cashutoken) { LaunchedEffect(key1 = cashutoken) {
launch(Dispatchers.IO) { launch(Dispatchers.IO) {
@ -44,13 +44,13 @@ fun CashuPreview(cashutoken: String, accountViewModel: AccountViewModel) {
} }
Crossfade(targetState = cachuData) { Crossfade(targetState = cachuData) {
if (it != null) { when (it) {
CashuPreview(it, accountViewModel) is GenericLoadable.Loaded<CashuToken> -> CashuPreview(it.loaded, accountViewModel)
} else { is GenericLoadable.Error<CashuToken> -> Text(
Text(
text = "$cashutoken ", text = "$cashutoken ",
style = LocalTextStyle.current.copy(textDirection = TextDirection.Content) style = LocalTextStyle.current.copy(textDirection = TextDirection.Content)
) )
else -> {}
} }
} }
} }

View File

@ -0,0 +1,19 @@
package com.vitorpamplona.amethyst.ui.components
import androidx.compose.runtime.Immutable
@Immutable
sealed class GenericLoadable<T> {
@Immutable
class Loading<T> : GenericLoadable<T>()
@Immutable
class Loaded<T>(val loaded: T) : GenericLoadable<T>()
@Immutable
class Empty<T> : GenericLoadable<T>()
@Immutable
class Error<T>(val errorMessage: String) : GenericLoadable<T>()
}