diff --git a/.idea/dictionaries/project.xml b/.idea/dictionaries/project.xml
index d12b73c..6320262 100644
--- a/.idea/dictionaries/project.xml
+++ b/.idea/dictionaries/project.xml
@@ -2,23 +2,40 @@
Aead
+ Bech
Bitrefill
+ Español
Nbits
Nostr
Tink
amboss
+ bech
+ bitcointxoko
+ btcpay
cltv
+ getnwckey
+ gudari
+ gudariwallet
hkdf
inflight
+ keyauth
+ lnaddr
+ lnaddress
lnbc
lnbits
lnurlp
+ lnurlw
msat
msats
nostr
+ nwccacherepository
+ satoshi
satoshis
sats
snackbar
+ snull
+ tink
+ walletconnect
\ No newline at end of file
diff --git a/app/src/main/java/com/bitcointxoko/gudariwallet/MainActivity.kt b/app/src/main/java/com/bitcointxoko/gudariwallet/MainActivity.kt
index 7b2787d..b2c673d 100644
--- a/app/src/main/java/com/bitcointxoko/gudariwallet/MainActivity.kt
+++ b/app/src/main/java/com/bitcointxoko/gudariwallet/MainActivity.kt
@@ -2,24 +2,18 @@ package com.bitcointxoko.gudariwallet
import android.Manifest
import android.app.PendingIntent
-import android.content.ActivityNotFoundException
import android.content.Intent
import android.content.IntentFilter
import android.nfc.NfcAdapter
import android.nfc.Tag
import android.os.Build
import android.os.Bundle
-import android.os.PowerManager
-import android.provider.Settings
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.activity.result.contract.ActivityResultContracts
import androidx.activity.viewModels
-import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.compose.runtime.*
-import androidx.core.content.edit
-import androidx.core.net.toUri
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.stateIn
diff --git a/app/src/main/java/com/bitcointxoko/gudariwallet/api/Adapters.kt b/app/src/main/java/com/bitcointxoko/gudariwallet/api/Adapters.kt
index 236dc6f..506e508 100644
--- a/app/src/main/java/com/bitcointxoko/gudariwallet/api/Adapters.kt
+++ b/app/src/main/java/com/bitcointxoko/gudariwallet/api/Adapters.kt
@@ -18,7 +18,7 @@ import kotlinx.serialization.json.jsonPrimitive
* - a JSON array ["Thanks!"]
* - null
*
- * Mirrors the behaviour of the old Gson FlexibleStringAdapter.
+ * Mirrors the behavior of the old Gson FlexibleStringAdapter.
*/
object FlexibleStringSerializer : KSerializer {
diff --git a/app/src/main/java/com/bitcointxoko/gudariwallet/api/JsonProvider.kt b/app/src/main/java/com/bitcointxoko/gudariwallet/api/JsonProvider.kt
index a6d6a7a..32ffb4a 100644
--- a/app/src/main/java/com/bitcointxoko/gudariwallet/api/JsonProvider.kt
+++ b/app/src/main/java/com/bitcointxoko/gudariwallet/api/JsonProvider.kt
@@ -3,7 +3,7 @@ package com.bitcointxoko.gudariwallet.api
import kotlinx.serialization.json.Json
/**
- * Single source of truth for the app's Json instance.
+ * Single source of truth for the app's JSON instance.
*
* All serialization/deserialization — Retrofit, DataStore caches,
* and WebSocket message parsing — must use this instance so that
diff --git a/app/src/main/java/com/bitcointxoko/gudariwallet/api/LNbitsClient.kt b/app/src/main/java/com/bitcointxoko/gudariwallet/api/LNbitsClient.kt
index 417cbe3..5121b5b 100644
--- a/app/src/main/java/com/bitcointxoko/gudariwallet/api/LNbitsClient.kt
+++ b/app/src/main/java/com/bitcointxoko/gudariwallet/api/LNbitsClient.kt
@@ -1,7 +1,6 @@
package com.bitcointxoko.gudariwallet.api
import com.bitcointxoko.gudariwallet.security.SecretStore
-import com.bitcointxoko.gudariwallet.util.WalletConstants
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
@@ -13,7 +12,6 @@ import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient
import retrofit2.Retrofit
import retrofit2.converter.kotlinx.serialization.asConverterFactory
-import java.util.concurrent.TimeUnit
import java.util.concurrent.atomic.AtomicReference
class LNbitsClient(secrets: SecretStore) {
@@ -38,8 +36,6 @@ class LNbitsClient(secrets: SecretStore) {
}
}
- // Single shared client — used by both Retrofit and WebSocket
- val httpClient: OkHttpClient get() = LNbitsHttpClient.instance
val api: LNbitsApi by lazy { buildApi() }
private fun buildApi(): LNbitsApi {
diff --git a/app/src/main/java/com/bitcointxoko/gudariwallet/api/Models.kt b/app/src/main/java/com/bitcointxoko/gudariwallet/api/Models.kt
index 3a84597..9855a82 100644
--- a/app/src/main/java/com/bitcointxoko/gudariwallet/api/Models.kt
+++ b/app/src/main/java/com/bitcointxoko/gudariwallet/api/Models.kt
@@ -251,7 +251,7 @@ data class SuccessAction(
* - a plain string "Thanks!"
* - null
*
- * kotlinx.serialization's default deserialiser throws when it sees a
+ * kotlinx.serialization's default deserializer throws when it sees a
* string where it expects {. This serializer handles all three cases.
*
* Applied via @Serializable(with = SuccessActionSerializer::class) on
diff --git a/app/src/main/java/com/bitcointxoko/gudariwallet/data/LNbitsWalletRepository.kt b/app/src/main/java/com/bitcointxoko/gudariwallet/data/LNbitsWalletRepository.kt
index 4c0ea53..2b76767 100644
--- a/app/src/main/java/com/bitcointxoko/gudariwallet/data/LNbitsWalletRepository.kt
+++ b/app/src/main/java/com/bitcointxoko/gudariwallet/data/LNbitsWalletRepository.kt
@@ -337,10 +337,8 @@ class LNbitsWalletRepository(
request : NwcRegistrationRequest
): NwcGetResponse {
Timber.d(
- "NWC [REGISTER ] pubkey=${pubkey.take(16)}… " +
- "permissions=${request.permissions} " +
- "expires_at=${request.expires_at} " +
- "budgets=${request.budgets.size}"
+ "%snull", "NWC [REGISTER ] pubkey=${pubkey.take(16)}… " +
+ "permissions=${request.permissions} "
)
val result = api.registerNwcKey(
adminKey = secrets.adminKey(),
diff --git a/app/src/main/java/com/bitcointxoko/gudariwallet/data/LightningAddressStore.kt b/app/src/main/java/com/bitcointxoko/gudariwallet/data/LightningAddressStore.kt
index 9a28eba..34386de 100644
--- a/app/src/main/java/com/bitcointxoko/gudariwallet/data/LightningAddressStore.kt
+++ b/app/src/main/java/com/bitcointxoko/gudariwallet/data/LightningAddressStore.kt
@@ -38,8 +38,7 @@ class LightningAddressStore(private val context: Context) {
.map { prefs ->
prefs[KEY_ADDRESS].also { address ->
_currentAddress = address
- Timber.d("LNADDR [CACHE ] read from cache: " +
- if (address != null) "\"$address\"" else "(empty — nothing cached yet)") }
+ Timber.d("LNADDR [CACHE ] read from cache: %s", if (address != null) "\"$address\"" else "(empty — nothing cached yet)") }
}
suspend fun isCacheStale(): Boolean {
@@ -53,9 +52,8 @@ class LightningAddressStore(private val context: Context) {
val fetchedAt = prefs[KEY_FETCHED_AT] ?: 0L
val age = System.currentTimeMillis() - fetchedAt
val isStale = address == null || age > LNADDRESS_TTL_MS
- Timber.d("LNADDR [TTL ] cached=${address != null} " +
- "age=${age / 1000}s ttl=${LNADDRESS_TTL_MS / 1000}s " +
- if (isStale) "→ cache stale, will fetch from API"
+ Timber.d("%s%s", "LNADDR [TTL ] cached=${address != null} " +
+ "age=${age / 1000}s ttl=${LNADDRESS_TTL_MS / 1000}s ", if (isStale) "→ cache stale, will fetch from API"
else "→ cache fresh, skipping API call")
isStale
}
diff --git a/app/src/main/java/com/bitcointxoko/gudariwallet/data/LnurlCacheRepository.kt b/app/src/main/java/com/bitcointxoko/gudariwallet/data/LnurlCacheRepository.kt
index bbb14c3..963ad39 100644
--- a/app/src/main/java/com/bitcointxoko/gudariwallet/data/LnurlCacheRepository.kt
+++ b/app/src/main/java/com/bitcointxoko/gudariwallet/data/LnurlCacheRepository.kt
@@ -39,7 +39,7 @@ class LnurlCacheRepository(context: Context) {
return null
}
- val response = deserialise(entity.responseJson) ?: run {
+ val response = deserialize(entity.responseJson) ?: run {
Timber.w("LNURL [DESER ERR ] $key — removing corrupt entry")
evict(key)
return null
@@ -104,7 +104,7 @@ class LnurlCacheRepository(context: Context) {
runCatching { dao.deleteByKey(key) }
}
- private fun deserialise(jsonString: String): LnurlScanResponse? =
+ private fun deserialize(jsonString: String): LnurlScanResponse? =
runCatching { json.decodeFromString(LnurlScanResponse.serializer(), jsonString) }
.getOrNull()
}
diff --git a/app/src/main/java/com/bitcointxoko/gudariwallet/security/CredentialsDataStore.kt b/app/src/main/java/com/bitcointxoko/gudariwallet/security/CredentialsDataStore.kt
index e535223..329f91f 100644
--- a/app/src/main/java/com/bitcointxoko/gudariwallet/security/CredentialsDataStore.kt
+++ b/app/src/main/java/com/bitcointxoko/gudariwallet/security/CredentialsDataStore.kt
@@ -1,20 +1,15 @@
package com.bitcointxoko.gudariwallet.security
import android.content.Context
-import timber.log.Timber
import androidx.datastore.core.DataStore
import androidx.datastore.core.DataStoreFactory
import androidx.datastore.core.handlers.ReplaceFileCorruptionHandler
import androidx.datastore.migrations.SharedPreferencesMigration
-import androidx.datastore.migrations.SharedPreferencesView
import com.bitcointxoko.gudariwallet.util.WalletConstants
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
-import kotlinx.coroutines.flow.first
-import kotlinx.coroutines.flow.map
import java.io.File
-import androidx.core.content.edit
/**
* Singleton DataStore for encrypted credentials.
@@ -27,8 +22,6 @@ import androidx.core.content.edit
* [cleanUpLegacyPrefs] once you've confirmed migration succeeded.
*/
object CredentialsDataStore {
- private const val TAG = "CredentialsDataStore"
-
@Volatile
private var instance: DataStore? = null
diff --git a/app/src/main/java/com/bitcointxoko/gudariwallet/security/CredentialsSerializer.kt b/app/src/main/java/com/bitcointxoko/gudariwallet/security/CredentialsSerializer.kt
index 0060c9b..d2b1a29 100644
--- a/app/src/main/java/com/bitcointxoko/gudariwallet/security/CredentialsSerializer.kt
+++ b/app/src/main/java/com/bitcointxoko/gudariwallet/security/CredentialsSerializer.kt
@@ -25,8 +25,8 @@ class CredentialsSerializer(
Timber.d("Credentials decrypted successfully — isOnboarded: ${result.isOnboarded}")
result
} catch (e: Exception) {
- Timber.e("Decryption failed — DataStore may be corrupt or key rotated", e)
- throw CorruptionException("Cannot read/decrypt credentials DataStore", e)
+ Timber.e("Decryption failed — DataStore may be corrupt or key rotated")
+ throw CorruptionException("Cannot read/decrypt credentials DataStore")
}
}
@@ -37,12 +37,10 @@ class CredentialsSerializer(
val encryptingStream = streamingAead.newEncryptingStream(output, AAD)
t.writeTo(encryptingStream) // returns Int — discarded by Unit return type
encryptingStream.close()
- Timber.d("Credentials encrypted and written — isOnboarded: ${t.isOnboarded}, " +
- "hasInvoiceKey: ${t.invoiceKey.isNotBlank()}, " +
- "hasAdminKey: ${t.adminKey.isNotBlank()}, " +
- "hasBaseUrl: ${t.baseUrl.isNotBlank()}")
+ Timber.d("%snull", "Credentials encrypted and written — isOnboarded: ${t.isOnboarded}, " +
+ "hasInvoiceKey: ${t.invoiceKey.isNotBlank()}, ")
} catch (e: Exception) {
- Timber.e("Encryption/write failed", e)
+ Timber.e("Encryption/write failed")
throw e
}
}
diff --git a/app/src/main/java/com/bitcointxoko/gudariwallet/security/CredentialsTinkManager.kt b/app/src/main/java/com/bitcointxoko/gudariwallet/security/CredentialsTinkManager.kt
index a7ffdb7..f573345 100644
--- a/app/src/main/java/com/bitcointxoko/gudariwallet/security/CredentialsTinkManager.kt
+++ b/app/src/main/java/com/bitcointxoko/gudariwallet/security/CredentialsTinkManager.kt
@@ -38,7 +38,7 @@ object CredentialsTinkManager {
Timber.i("StreamingAead primitive acquired successfully")
}
} catch (e: Exception) {
- Timber.e("Failed to initialise StreamingAead — Keystore may be unavailable", e)
+ Timber.e("Failed to initialise StreamingAead — Keystore may be unavailable")
throw e
}
}
diff --git a/app/src/main/java/com/bitcointxoko/gudariwallet/service/NodeAliasService.kt b/app/src/main/java/com/bitcointxoko/gudariwallet/service/NodeAliasService.kt
index 232d3d4..64c93df 100644
--- a/app/src/main/java/com/bitcointxoko/gudariwallet/service/NodeAliasService.kt
+++ b/app/src/main/java/com/bitcointxoko/gudariwallet/service/NodeAliasService.kt
@@ -41,7 +41,7 @@ class NodeAliasService(
repo.put(pubkey, alias)
// 4. Publish to StateFlow
- _aliases.value = _aliases.value + (pubkey to alias)
+ _aliases.value += (pubkey to alias)
Timber.d("ALIAS [FETCHED ] $pubkey → \"$alias\"")
return alias
diff --git a/app/src/main/java/com/bitcointxoko/gudariwallet/service/WalletNotificationService.kt b/app/src/main/java/com/bitcointxoko/gudariwallet/service/WalletNotificationService.kt
index c94fee4..08f8446 100644
--- a/app/src/main/java/com/bitcointxoko/gudariwallet/service/WalletNotificationService.kt
+++ b/app/src/main/java/com/bitcointxoko/gudariwallet/service/WalletNotificationService.kt
@@ -30,6 +30,7 @@ import okhttp3.Request
import okhttp3.Response
import okhttp3.WebSocket
import okhttp3.WebSocketListener
+import kotlin.time.Duration.Companion.milliseconds
private const val TAG = "WalletNotifService"
@@ -271,7 +272,7 @@ class WalletNotificationService : Service() {
reconnectJob?.cancel()
reconnectJob = serviceScope.launch {
- delay(backoff)
+ delay(backoff.milliseconds)
openWebSocket()
}
}
diff --git a/app/src/main/java/com/bitcointxoko/gudariwallet/ui/WalletScreen.kt b/app/src/main/java/com/bitcointxoko/gudariwallet/ui/WalletScreen.kt
index 7bd3ade..ddafcef 100644
--- a/app/src/main/java/com/bitcointxoko/gudariwallet/ui/WalletScreen.kt
+++ b/app/src/main/java/com/bitcointxoko/gudariwallet/ui/WalletScreen.kt
@@ -71,6 +71,7 @@ import com.bitcointxoko.gudariwallet.ui.send.SendScreen
import com.bitcointxoko.gudariwallet.ui.send.SendStrings
import com.bitcointxoko.gudariwallet.util.SendInputType
import kotlinx.coroutines.delay
+import kotlin.time.Duration.Companion.milliseconds
// ── Tab destinations ──────────────────────────────────────────────────────────
// Note: label and icon are now resolved at the call site via LocalAppStrings,
@@ -205,7 +206,7 @@ fun WalletScreen(
LaunchedEffect(clipboardOffer) {
if (clipboardOffer is ClipboardOfferState.Detected) {
- delay(8_000)
+ delay(8_000.milliseconds)
vm.dismissClipboardOffer()
}
}
@@ -215,7 +216,7 @@ fun WalletScreen(
LaunchedEffect(nfcOffer) {
if (nfcOffer is NfcOfferState.Detected) {
- delay(8_000)
+ delay(8_000.milliseconds)
nfcVm.dismissNfcOffer()
}
}
diff --git a/app/src/main/java/com/bitcointxoko/gudariwallet/ui/WalletViewModelFactory.kt b/app/src/main/java/com/bitcointxoko/gudariwallet/ui/WalletViewModelFactory.kt
index daec30d..bd1ac46 100644
--- a/app/src/main/java/com/bitcointxoko/gudariwallet/ui/WalletViewModelFactory.kt
+++ b/app/src/main/java/com/bitcointxoko/gudariwallet/ui/WalletViewModelFactory.kt
@@ -13,7 +13,6 @@ import com.bitcointxoko.gudariwallet.data.LightningAddressStore
import com.bitcointxoko.gudariwallet.data.LnurlCacheRepository
import com.bitcointxoko.gudariwallet.data.NwcCacheRepository
import com.bitcointxoko.gudariwallet.data.PaymentCacheRepository
-import com.bitcointxoko.gudariwallet.data.db.AppDatabase
import com.bitcointxoko.gudariwallet.security.EncryptedSecretStore
import com.bitcointxoko.gudariwallet.service.NodeAliasService
import com.bitcointxoko.gudariwallet.ui.balance.BalanceViewModel
diff --git a/app/src/main/java/com/bitcointxoko/gudariwallet/ui/common/BrightnessController.kt b/app/src/main/java/com/bitcointxoko/gudariwallet/ui/common/BrightnessController.kt
index 2acef95..26f386e 100644
--- a/app/src/main/java/com/bitcointxoko/gudariwallet/ui/common/BrightnessController.kt
+++ b/app/src/main/java/com/bitcointxoko/gudariwallet/ui/common/BrightnessController.kt
@@ -1,9 +1,8 @@
package com.bitcointxoko.gudariwallet.ui.common
-import android.app.Activity
import android.view.WindowManager
+import androidx.activity.compose.LocalActivity
import androidx.compose.runtime.*
-import androidx.compose.ui.platform.LocalContext
/**
* Manages screen brightness for QR-display screens.
@@ -12,12 +11,12 @@ import androidx.compose.ui.platform.LocalContext
*/
@Composable
fun rememberBrightnessController(): BrightnessController {
- val window = (LocalContext.current as? Activity)?.window
+ val window = (LocalActivity.current)?.window
var isOn by remember { mutableStateOf(false) }
- // Sync side-effect: no coroutine needed
+ // Sync side effect: no coroutine needed
SideEffect {
- window?.attributes = window?.attributes?.apply {
+ window?.attributes = window.attributes?.apply {
screenBrightness = if (isOn) WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_FULL
else WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_NONE
}
@@ -25,7 +24,7 @@ fun rememberBrightnessController(): BrightnessController {
DisposableEffect(Unit) {
onDispose {
- window?.attributes = window?.attributes?.apply {
+ window?.attributes = window.attributes?.apply {
screenBrightness = WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_NONE
}
}
diff --git a/app/src/main/java/com/bitcointxoko/gudariwallet/util/IntentUtils.kt b/app/src/main/java/com/bitcointxoko/gudariwallet/util/IntentUtils.kt
index da1d203..1561c03 100644
--- a/app/src/main/java/com/bitcointxoko/gudariwallet/util/IntentUtils.kt
+++ b/app/src/main/java/com/bitcointxoko/gudariwallet/util/IntentUtils.kt
@@ -23,7 +23,7 @@ object IntentUtils {
* Returns a raw payment URI string if the intent carries one, else null.
*
* Handles:
- * - ACTION_VIEW with a recognised scheme (BTCPay "Pay in wallet", browser links)
+ * - ACTION_VIEW with a recognized scheme (BTCPay "Pay in wallet", browser links)
* - ACTION_SEND with text/plain (share sheet from another app)
*/
fun extractPaymentUri(intent: Intent?): String? {
diff --git a/app/src/main/java/com/bitcointxoko/gudariwallet/util/LnurlMetadataParser.kt b/app/src/main/java/com/bitcointxoko/gudariwallet/util/LnurlMetadataParser.kt
index 7264cfd..ee42bbb 100644
--- a/app/src/main/java/com/bitcointxoko/gudariwallet/util/LnurlMetadataParser.kt
+++ b/app/src/main/java/com/bitcointxoko/gudariwallet/util/LnurlMetadataParser.kt
@@ -40,7 +40,7 @@ object LnurlMetadataParser {
/**
* Returns the display label for a LNURL payment target.
* If [lnurl] is a Lightning Address (contains '@'), returns it as-is.
- * Otherwise returns the [domain] of the LNURL endpoint.
+ * Otherwise, returns the [domain] of the LNURL endpoint.
*/
fun payingToLabel(lnurl: String, domain: String): String =
if ('@' in lnurl) lnurl else domain
\ No newline at end of file