1
\$\begingroup\$

I'm only asking because I'm new and don't know enough to have a concrete question. Did I do this correctly? I worked on this until the code performed as expected, but I don't think I'm done.

In looking this over I'm sure you'll see something that bothers you. I am unsure of my changes, and I'd like feedback prior to writing the rest of the message functions and response handlers.

GitHub commit

diff --git a/ant.properties b/ant.properties
new file mode 100644
index 0000000..6b22946
--- /dev/null
+++ b/ant.properties
@@ -0,0 +1,2 @@
+java.source=1.7
+java.target=1.7
diff --git a/src/com/satoshilabs/trezor/Trezor.java b/src/com/satoshilabs/trezor/Trezor.java
index 41f9815..fe4d471 100644
--- a/src/com/satoshilabs/trezor/Trezor.java
+++ b/src/com/satoshilabs/trezor/Trezor.java
@@ -7,7 +7,11 @@ import java.util.Iterator;

 import com.google.protobuf.InvalidProtocolBufferException;
 import com.google.protobuf.Message;
+import com.google.protobuf.Descriptors;
+import com.satoshilabs.trezor.protobuf.TrezorMessage;
 import com.satoshilabs.trezor.protobuf.TrezorMessage.*;
+import com.satoshilabs.trezor.protobuf.TrezorType;
+import com.satoshilabs.trezor.TrezorGUICallback;

 import android.content.Context;
 import android.hardware.usb.UsbConstants;
@@ -19,9 +23,19 @@ import android.hardware.usb.UsbManager;
 import android.hardware.usb.UsbRequest;
 import android.util.Log;

+/* Stub for empty TrezorGUICallback */
+class _TrezorGUICallback implements TrezorGUICallback {
+   public String PinMatrixRequest() { return ""; }
+   public String PassphraseRequest() { return ""; }
+}
+
 public class Trezor {

    public static Trezor getDevice(Context context) {
+       return getDevice(context,new _TrezorGUICallback());
+   }
+
+   public static Trezor getDevice(Context context, TrezorGUICallback guicall) {
        UsbManager manager = (UsbManager)context.getSystemService(Context.USB_SERVICE);
        HashMap<String, UsbDevice> deviceList = manager.getDeviceList();
        Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();
@@ -80,7 +94,7 @@ public class Trezor {
                continue;
            }
            // all OK - return the class
-           return new Trezor(device, conn, iface, epr, epw);
+           return new Trezor(guicall, device, conn, iface, epr, epw);
        }
        return null;
    }
@@ -89,8 +103,10 @@ public class Trezor {
    private UsbDeviceConnection conn;
    private String serial;
    private UsbEndpoint epr, epw;
+   private TrezorGUICallback guicall;

-   public Trezor(UsbDevice device, UsbDeviceConnection conn, UsbInterface iface, UsbEndpoint epr, UsbEndpoint epw) {
+   public Trezor(TrezorGUICallback guicall, UsbDevice device, UsbDeviceConnection conn, UsbInterface iface, UsbEndpoint epr, UsbEndpoint epw) {
+       this.guicall = guicall;
 //     this.device = device;
        this.conn = conn;
        this.epr = epr;
@@ -205,4 +221,93 @@ public class Trezor {
        return messageRead();
    }

+   final protected static char[] hexArray = "0123456789ABCDEF".toCharArray();
+   private static String bytesToHex(byte[] bytes) {
+       char[] hexChars = new char[bytes.length * 2];
+       for ( int j = 0; j < bytes.length; j++ ) {
+           int v = bytes[j] & 0xFF;
+           hexChars[j * 2] = hexArray[v >>> 4];
+           hexChars[j * 2 + 1] = hexArray[v & 0x0F];
+       }
+       return new String(hexChars);
+   }
+
+   private String _get(Message resp) {
+       switch (resp.getClass().getSimpleName()) {
+       case "Success": {
+           TrezorMessage.Success r = (TrezorMessage.Success)resp;
+           if(r.hasPayload())throw new IllegalArgumentException();
+           if(r.hasMessage())return r.getMessage();
+           return ""; }
+       case "Failure":
+           throw new IllegalStateException();
+       /* User can catch ButtonRequest to Cancel by not calling _get */
+       case "ButtonRequest":
+           return _get(this.send(TrezorMessage.ButtonAck.newBuilder().build()));
+       case "PinMatrixRequest":
+           return _get(this.send(
+               TrezorMessage.PinMatrixAck.newBuilder().
+               setPin(this.guicall.PinMatrixRequest()).
+               build()));
+       case "PassphraseRequest":
+           return _get(this.send(
+               TrezorMessage.PassphraseAck.newBuilder().
+               /* TODO: UTF8 VS Unicode... Fight! */
+               setPassphrase(this.guicall.PassphraseRequest()).
+               build()));
+       case "PublicKey": {
+           TrezorMessage.PublicKey r = (TrezorMessage.PublicKey)resp;
+           if(!r.hasNode())throw new IllegalArgumentException();
+           TrezorType.HDNodeType N = r.getNode();
+           String NodeStr = ((N.hasDepth())?N.getDepth():"") +"%"+
+               ((N.hasFingerprint())?N.getFingerprint():"") +"%"+
+               ((N.hasChildNum())?N.getChildNum():"") +"%"+
+               ((N.hasChainCode())?bytesToHex(N.getChainCode().toByteArray()):"") +"%"+
+               ((N.hasPrivateKey())?bytesToHex(N.getPrivateKey().toByteArray()):"") +"%"+
+               ((N.hasPublicKey())?bytesToHex(N.getPublicKey().toByteArray()):"") +"%"+
+               "";
+           if(r.hasXpub())
+               return NodeStr + ":!:" + r.getXpub() + ":!:" +
+                   bytesToHex(r.getXpubBytes().toByteArray());
+           return NodeStr; }
+       }
+//     throw new IllegalArgumentException();
+       return resp.getClass().getSimpleName();
+   }
+
+   public String MessagePing() {
+       return _get(this.send(TrezorMessage.Ping.newBuilder().build()));
+   }
+
+   public String MessagePing(String msg) {
+       return _get(this.send(
+           TrezorMessage.Ping.newBuilder().
+           setMessage(msg).
+           build()));
+   }
+
+   public String MessagePing(String msg, Boolean ButtonProtection) {
+       return _get(this.send(
+           TrezorMessage.Ping.newBuilder().
+           setMessage(msg).
+           setButtonProtection(ButtonProtection).
+           build()));
+   }
+
+   public String MessageGetPublicKey() {
+       return _get(this.send(
+           TrezorMessage.GetPublicKey.newBuilder().
+           clearAddressN().
+           addAddressN(1).
+           build()));
+   }
+
+   public String MessageGetPublicKey(Integer[] addrn) {
+       return _get(this.send(
+           TrezorMessage.GetPublicKey.newBuilder().
+           clearAddressN().
+           addAllAddressN(Arrays.asList(addrn)).
+           build()));
+   }
+
 }
diff --git a/src/com/satoshilabs/trezor/TrezorGUICallback.java b/src/com/satoshilabs/trezor/TrezorGUICallback.java
new file mode 100644
index 0000000..61ec703
--- /dev/null
+++ b/src/com/satoshilabs/trezor/TrezorGUICallback.java
@@ -0,0 +1,7 @@
+package com.satoshilabs.trezor;
+
+public interface TrezorGUICallback {
+        public String PinMatrixRequest();
+        public String PassphraseRequest();
+}
+
\$\endgroup\$
  • \$\begingroup\$ You probably didn't want to include the git-boilerplate to the code in your question... I suggest you edit the leading +and the additonal diff information out... \$\endgroup\$ – Vogel612 Nov 17 '14 at 18:13
  • \$\begingroup\$ Could you tell us the purpose of the enhancement, and your intended future direction? \$\endgroup\$ – 200_success Nov 17 '14 at 19:22
  • \$\begingroup\$ Thanks for taking a look. The original purpose of this class was to expose the Trezor's Message API. The enhancement is to provide helper functions that expose the Message API as a Java API, for the most common cases. \$\endgroup\$ – Mike Mestnik Nov 18 '14 at 19:22
  • \$\begingroup\$ Is this a good Java API, should the functions be filled out as these examples are for the rest of the messages and the same for the _get function? What would a Java developer see as the future direction? \$\endgroup\$ – Mike Mestnik Nov 18 '14 at 19:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.