/// <summary>Get the Extended Public Key from the device for the BIP32 path specified.</summary> /// <param name="pinChallenge">Callback that gets </param> /// <param name="accountPath">BIP32 path e.g. "44'/0'/0'/0/0 = first Bitcoin account, first public key., from this you can derive the address.</param> /// <returns>The public key of the for the account at the path specified.</returns> public PublicKey GetPublicKey(Func <PinMatrixRequestType?, string> pinChallenge, string accountPath) { // Get the path as units var path = NBitcoin.KeyPath.Parse(accountPath); // Build the message var xpub = new GetPublicKey { AddressN = new List <uint>(path.Indexes), EcdsaCurveName = "secp256k1", ShowDisplay = false }; // Serialize it to bytes var msg = Contracts.GetPublicKey.SerializeToBytes(xpub); // Send the message to the device if (!_communicator.SendMessage(msg, MessageType.MessageType_GetPublicKey)) { throw new ApplicationException("Error writing to device"); } // Get the response from the device MessageType recievedType; var received = _communicator.RecieveMessage(out recievedType); if (recievedType == MessageType.MessageType_PinMatrixRequest) { var pinRequest = PinMatrixRequest.Deserialize(received); var pin = pinChallenge(pinRequest.Type); if (!_communicator.SendMessage(PinMatrixAck.SerializeToBytes(new PinMatrixAck { Pin = pin }), MessageType.MessageType_PinMatrixAck)) { throw new ApplicationException("Error writing to device"); } received = _communicator.RecieveMessage(out recievedType); } // PublicKey received if (recievedType == MessageType.MessageType_PublicKey) { return(PublicKey.Deserialize(received)); } // The device returned Failure if (recievedType == MessageType.MessageType_Failure) { throw new KeepKeyException(Failure.Deserialize(received)); } throw new NotImplementedException("Unable to process unexpected message type: " + recievedType); }
/// <summary>Displays a message on the KeepKey screen. Supply true to the second parameter to force the user to press the device button.</summary> /// <param name="message">The message to display. Note the maximum number of characters is approximately 130 - text longer than this gets truncated by the device.</param> /// <param name="buttonProtection">true to wait for the user to press and hold the button on the device, false to return the message immediately.</param> /// <returns></returns> public string Ping(string message, bool buttonProtection = true) { // Build the message var ping = new Ping { // Provide ALL fields Message = message, ButtonProtection = buttonProtection, PinProtection = false, PassphraseProtection = false }; // Serialize it to bytes var msg = Contracts.Ping.SerializeToBytes(ping); // Send the message to the device if (!_communicator.SendMessage(msg, MessageType.MessageType_Ping)) { throw new ApplicationException("Error writing to device"); } // Get the response from the device MessageType recievedType; var received = _communicator.RecieveMessage(out recievedType); // ButtonRequest was received if (recievedType == MessageType.MessageType_ButtonRequest) { // Acknowledge the button request & wait for the next response if (!_communicator.SendMessage(ButtonAck.SerializeToBytes(new ButtonAck()), MessageType.MessageType_ButtonAck)) { throw new ApplicationException("Error writing to device"); } received = _communicator.RecieveMessage(out recievedType); } // The device returned Success if (recievedType == MessageType.MessageType_Success) { return(Success.Deserialize(received).Message); } // The device returned Failure if (recievedType == MessageType.MessageType_Failure) { var failure = Failure.Deserialize(received); return(failure.Code.HasValue ? $"{failure.Code.GetValueOrDefault()} - {failure.Message}" : failure.Message); } throw new NotImplementedException("Unable to process unexpected message type: " + recievedType); }