Hummingbird is a Java implementation of the Uniform Resources (UR) specification. It is a direct port of the URKit implementation by Wolf McNally. It contains both the classes to represent a UR, and a UR encoder and decoder to encode and decode to/from the QR representations. Hummingbird requires a minimum of Java 8.
Hummingbird is hosted in Maven Central and can be added as a dependency with the following:
implementation('com.sparrowwallet:hummingbird:1.7.4')
Decoding a UR can be done as follows (here decoding a crypto-psbt
UR type):
URDecoder decoder = new URDecoder();
while(decoder.getResult() == null) {
//Loop adding QR fragments to the decoder until it has a result
String qrText = getFromNextQR();
decoder.receivePart(qrText);
}
URDecoder.Result urResult = decoder.getResult();
if(urResult.type == ResultType.SUCCESS) {
if(urResult.ur.getType().equals(UR.CRYPTO_PSBT_TYPE)) {
byte[] psbt = urResult.ur.toBytes();
}
}
Encoding a UR:
final int MIN_FRAGMENT_LENGTH = 10;
final int MAX_FRAGMENT_LENGTH = 100;
String type = UR.BYTES_TYPE;
UR ur = UR.fromBytes(type, data);
UREncoder encoder = new UREncoder(ur, MAX_FRAGMENT_LENGTH, MIN_FRAGMENT_LENGTH, 0);
while(true) {
String fragment = encoder.nextPart();
//Show UR fragment as QR code...
}
Hummingbird also includes a type registry to assist with encoding and decoding from CBOR to and from POJOs:
RegistryType urRegistryType = ur.getRegistryType();
if(urRegistryType.equals(RegistryType.CRYPTO_PSBT)) {
CryptoPSBT cryptoPSBT = (CryptoPSBT)ur.decodeFromRegistry();
UR cryptoPSBTUR = cryptoPSBT.toUR();
} else if(urRegistryType.equals(RegistryType.CRYPTO_ADDRESS)) {
CryptoAddress cryptoAddress = (CryptoAddress)ur.decodeFromRegistry();
UR cryptoAddressUR = cryptoAddress.toUR();
} else if(urRegistryType.equals(RegistryType.CRYPTO_HDKEY)) {
CryptoHDKey cryptoHDKey = (CryptoHDKey)ur.decodeFromRegistry();
UR cryptoHDKeyUR = cryptoHDKey.toUR();
} else if(urRegistryType.equals(RegistryType.CRYPTO_OUTPUT)) {
CryptoOutput cryptoOutput = (CryptoOutput)ur.decodeFromRegistry();
UR cryptoOutputUR = cryptoOutput.toUR();
} else if(urRegistryType.equals(RegistryType.CRYPTO_ACCOUNT)) {
CryptoAccount cryptoAccount = (CryptoAccount)ur.decodeFromRegistry();
UR cryptoAccountUR = cryptoAccount.toUR();
}
See RegistryType.java
for the full list of supported types and their POJO implementation classes where available.
Encoding and decoding with the UR1.0 specification is supported. Note however that these classes are deprecated and will be removed in a future release.
//decoding
LegacyURDecoder decoder = new LegacyURDecoder();
while(!decoder.isComplete()) {
//Loop adding QR fragments to the decoder until it has a result
String qrText = getFromNextQR();
decoder.receivePart(qrText);
}
UR ur = decoder.decode();
//encoding
LegacyUREncoder encoder = new LegacyUREncoder(ur);
String[] fragments = legacyUREncoder.encode();
Hummingbird has a thorough testsuite ported from URKit. The tests can be run with:
./gradlew test
Hummingbird is licensed under the Apache 2 software license.