mirror of
https://github.com/pezkuwichain/pezkuwi-wallet-android.git
synced 2026-07-22 17:15:48 +00:00
fix: recognize BIP21 bitcoin: URIs when scanning a QR code
Confirmed live: sending BTC back out via QR-scanning an external wallet's/ exchange's receive address failed with a generic "QR can't be decoded" error. Root cause: the QR decoder only ever recognized two shapes - substrate:<address>:<pubkey> triples and bare address strings - neither of which matches the bitcoin:<address>?amount=... BIP21 URI most wallets and exchanges generate for a BTC address. Adds BitcoinUriQrFormat, tried alongside the existing formats, that strips the scheme and query string before validating the address the normal way.
This commit is contained in:
+36
@@ -0,0 +1,36 @@
|
|||||||
|
package io.novafoundation.nova.runtime.multiNetwork.qr
|
||||||
|
|
||||||
|
import io.novasama.substrate_sdk_android.encrypt.qr.PublicQrFormat
|
||||||
|
import io.novasama.substrate_sdk_android.encrypt.qr.QrFormat
|
||||||
|
|
||||||
|
private const val BITCOIN_URI_SCHEME = "bitcoin:"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* BIP21 URI (`bitcoin:<address>?amount=...&label=...`) - the standard QR payload most wallets/exchanges generate
|
||||||
|
* for a Bitcoin receive address. Neither `SubstrateQrFormat` (expects a `substrate:<address>:<pubkey>` triple)
|
||||||
|
* nor `AddressQrFormat` (treats the whole QR content as a bare address) recognize this, so scanning an external
|
||||||
|
* wallet's or exchange's BTC address QR failed outright with the generic "QR can't be decoded" error - confirmed
|
||||||
|
* live against a real BTC withdrawal QR.
|
||||||
|
*/
|
||||||
|
class BitcoinUriQrFormat(
|
||||||
|
private val addressValidator: (String) -> Boolean
|
||||||
|
) : PublicQrFormat {
|
||||||
|
|
||||||
|
override fun encode(payload: PublicQrFormat.Payload): String {
|
||||||
|
return "$BITCOIN_URI_SCHEME${payload.address}"
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun decode(qrContent: String): PublicQrFormat.Payload {
|
||||||
|
if (!qrContent.startsWith(BITCOIN_URI_SCHEME, ignoreCase = true)) {
|
||||||
|
throw QrFormat.InvalidFormatException("Not a bitcoin: URI")
|
||||||
|
}
|
||||||
|
|
||||||
|
val address = qrContent.substring(BITCOIN_URI_SCHEME.length).substringBefore('?')
|
||||||
|
|
||||||
|
return if (addressValidator(address)) {
|
||||||
|
PublicQrFormat.Payload(address = address)
|
||||||
|
} else {
|
||||||
|
throw QrFormat.InvalidFormatException("Supplied bitcoin: URI has an invalid address")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+2
@@ -8,10 +8,12 @@ class MultiChainQrSharingFactory {
|
|||||||
|
|
||||||
fun create(addressValidator: (String) -> Boolean): QrSharing {
|
fun create(addressValidator: (String) -> Boolean): QrSharing {
|
||||||
val substrateFormat = SubstrateQrFormat()
|
val substrateFormat = SubstrateQrFormat()
|
||||||
|
val bitcoinUriFormat = BitcoinUriQrFormat(addressValidator)
|
||||||
val onlyAddressFormat = AddressQrFormat(addressValidator)
|
val onlyAddressFormat = AddressQrFormat(addressValidator)
|
||||||
|
|
||||||
val formats = listOf(
|
val formats = listOf(
|
||||||
substrateFormat,
|
substrateFormat,
|
||||||
|
bitcoinUriFormat,
|
||||||
onlyAddressFormat
|
onlyAddressFormat
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user