Home

Awesome

Hummingbird

Java implementation of Uniform Resources (UR)

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.

Setup

Hummingbird is hosted in Maven Central and can be added as a dependency with the following:

implementation('com.sparrowwallet:hummingbird:1.7.4')

Usage

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.

Legacy (UR1.0) Encoding and Decoding

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();

Testing

Hummingbird has a thorough testsuite ported from URKit. The tests can be run with:

./gradlew test

License

Hummingbird is licensed under the Apache 2 software license.

Dependencies