@@ -86,6 +86,7 @@ import to.bitkit.models.Toast
8686import to.bitkit.models.TransactionSpeed
8787import to.bitkit.models.safe
8888import to.bitkit.models.toActivityFilter
89+ import to.bitkit.models.toLdkNetwork
8990import to.bitkit.models.toTxType
9091import to.bitkit.repositories.ActivityRepo
9192import to.bitkit.repositories.BackupRepo
@@ -107,6 +108,7 @@ import to.bitkit.ui.shared.toast.ToastEventBus
107108import to.bitkit.ui.shared.toast.ToastQueueManager
108109import to.bitkit.ui.sheets.SendRoute
109110import to.bitkit.ui.theme.TRANSITION_SCREEN_MS
111+ import to.bitkit.utils.Bip21Utils
110112import to.bitkit.utils.Logger
111113import to.bitkit.utils.NetworkValidationHelper
112114import to.bitkit.utils.jsonLogOf
@@ -701,6 +703,16 @@ class AppViewModel @Inject constructor(
701703 }
702704
703705 private suspend fun validateAddressWithFeedback (input : String ) = withContext(bgDispatcher) {
706+ // TODO Workaround for https://github.com/synonymdev/bitkit-core/issues/63
707+ if (Bip21Utils .isDuplicatedBip21(input)) {
708+ showAddressValidationError(
709+ titleRes = R .string.other__scan_err_decoding,
710+ descriptionRes = R .string.other__scan__error__generic,
711+ testTag = " DuplicatedBip21Toast" ,
712+ )
713+ return @withContext
714+ }
715+
704716 val scanResult = runCatching { decode(input) }
705717
706718 if (scanResult.isFailure) {
@@ -747,9 +759,17 @@ class AppViewModel @Inject constructor(
747759 }
748760
749761 private fun validateOnChainAddress (invoice : OnChainInvoice ) {
750- // Check network mismatch
751- val addressNetwork = NetworkValidationHelper .getAddressNetwork(invoice.address)
752- if (NetworkValidationHelper .isNetworkMismatch(addressNetwork, Env .network)) {
762+ val validatedAddress = runCatching { validateBitcoinAddress(invoice.address) }
763+ .getOrElse {
764+ showAddressValidationError(
765+ titleRes = R .string.other__scan_err_decoding,
766+ descriptionRes = R .string.wallet__error_invalid_bitcoin_address,
767+ testTag = " InvalidAddressToast" ,
768+ )
769+ return
770+ }
771+
772+ if (NetworkValidationHelper .isNetworkMismatch(validatedAddress.network.toLdkNetwork(), Env .network)) {
753773 showAddressValidationError(
754774 titleRes = R .string.other__scan_err_decoding,
755775 descriptionRes = R .string.other__scan__error__generic,
@@ -974,6 +994,17 @@ class AppViewModel @Inject constructor(
974994 resetSendState()
975995 resetQuickPay()
976996
997+ // TODO Workaround for https://github.com/synonymdev/bitkit-core/issues/63
998+ if (Bip21Utils .isDuplicatedBip21(result)) {
999+ toast(
1000+ type = Toast .ToastType .ERROR ,
1001+ title = context.getString(R .string.other__scan_err_decoding),
1002+ description = context.getString(R .string.other__scan__error__generic),
1003+ testTag = " DuplicatedBip21Toast" ,
1004+ )
1005+ return @withContext
1006+ }
1007+
9771008 @Suppress(" ForbiddenComment" ) // TODO: wrap `decode` from bindings in a `CoreService` method and call that one
9781009 val scan = runCatching { decode(result) }
9791010 .onFailure { Logger .error(" Failed to decode scan data: '$result '" , it, context = TAG ) }
@@ -1000,11 +1031,20 @@ class AppViewModel @Inject constructor(
10001031 }
10011032 }
10021033
1003- @Suppress(" LongMethod" , " CyclomaticComplexMethod" )
1034+ @Suppress(" LongMethod" , " CyclomaticComplexMethod" , " ReturnCount " )
10041035 private suspend fun onScanOnchain (invoice : OnChainInvoice , scanResult : String ) {
1005- // Check network mismatch
1006- val addressNetwork = NetworkValidationHelper .getAddressNetwork(invoice.address)
1007- if (NetworkValidationHelper .isNetworkMismatch(addressNetwork, Env .network)) {
1036+ val validatedAddress = runCatching { validateBitcoinAddress(invoice.address) }
1037+ .getOrElse {
1038+ toast(
1039+ type = Toast .ToastType .ERROR ,
1040+ title = context.getString(R .string.other__scan_err_decoding),
1041+ description = context.getString(R .string.wallet__error_invalid_bitcoin_address),
1042+ testTag = " InvalidAddressToast" ,
1043+ )
1044+ return
1045+ }
1046+
1047+ if (NetworkValidationHelper .isNetworkMismatch(validatedAddress.network.toLdkNetwork(), Env .network)) {
10081048 toast(
10091049 type = Toast .ToastType .ERROR ,
10101050 title = context.getString(R .string.other__scan_err_decoding),
@@ -1484,18 +1524,9 @@ class AppViewModel @Inject constructor(
14841524 when (_sendUiState .value.payMethod) {
14851525 SendMethod .ONCHAIN -> {
14861526 val address = _sendUiState .value.address
1487- // TODO validate early, validate network & address types, showing detailed errors
1488- val validatedAddress = runCatching { validateBitcoinAddress(address) }
1489- .getOrElse { e ->
1490- Logger .error(" Invalid bitcoin send address: '$address '" , e, context = TAG )
1491- toast(Exception (context.getString(R .string.wallet__error_invalid_bitcoin_address)))
1492- hideSheet()
1493- return
1494- }
1495-
14961527 val tags = _sendUiState .value.selectedTags
14971528
1498- sendOnchain(validatedAddress. address, amount, tags = tags)
1529+ sendOnchain(address, amount, tags = tags)
14991530 .onSuccess { txId ->
15001531 Logger .info(" Onchain send result txid: $txId " , context = TAG )
15011532 handlePaymentSuccess(
0 commit comments