Pure Kotlin implementation of the BBQr protocol for splitting and joining binary data across multiple QR codes, optimized for Bitcoin-related payloads like PSBTs and transactions.
- Pure Kotlin/JVM — no native dependencies, no JNI/JNA
- Cross-compatible with Rust and Python BBQr implementations
- Zlib compression with automatic fallback to Base32 when compression doesn't help
- Streaming/incremental QR scanning via
ContinuousJoiner - Automatic QR version selection for optimal fit
- Supports PSBT, Transaction, JSON, CBOR, and Unicode text file types
- Up to 1295 QR code parts per payload
dependencies {
implementation("com.gorunjinian:bbqr:1.0.3")
}dependencies {
implementation 'com.gorunjinian:bbqr:1.0.3'
}import com.gorunjinian.bbqr.*
val psbtBytes: ByteArray = // ... your PSBT data
val split = SplitResult.fromData(psbtBytes, FileType.Psbt)
val qrParts: List<String> = split.parts
// Each string in qrParts is the content for one QR codeimport com.gorunjinian.bbqr.*
val joined = Joined.fromParts(qrParts)
val originalData: ByteArray = joined.data
val fileType: FileType = joined.fileTypeimport com.gorunjinian.bbqr.*
val joiner = ContinuousJoiner()
fun onQrCodeScanned(qrContent: String) {
when (val result = joiner.addPart(qrContent)) {
is ContinuousJoinResult.NotStarted -> { /* no valid data yet */ }
is ContinuousJoinResult.InProgress -> {
println("${result.partsLeft} parts remaining")
}
is ContinuousJoinResult.Complete -> {
val data = result.joined.data
val fileType = result.joined.fileType
// handle complete data
}
}
}val split = SplitResult.fromData(
psbtBytes,
FileType.Psbt,
SplitOptions(
encoding = Encoding.Zlib,
minSplitNumber = 1,
maxSplitNumber = 50,
minVersion = Version.V05,
maxVersion = Version.V20,
),
)./gradlew build./gradlew testSee BBQR_IMPLEMENTATION.md for the full API reference, protocol details, and usage examples.
See the BBQr specification for the protocol details.
MIT