"use strict";
var __assign = (this && this.__assign) || function () {
    __assign = Object.assign || function(t) {
        for (var s, i = 1, n = arguments.length; i < n; i++) {
            s = arguments[i];
            for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
                t[p] = s[p];
        }
        return t;
    };
    return __assign.apply(this, arguments);
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var __generator = (this && this.__generator) || function (thisArg, body) {
    var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
    return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
    function verb(n) { return function (v) { return step([n, v]); }; }
    function step(op) {
        if (f) throw new TypeError("Generator is already executing.");
        while (_) try {
            if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
            if (y = 0, t) op = [op[0] & 2, t.value];
            switch (op[0]) {
                case 0: case 1: t = op; break;
                case 4: _.label++; return { value: op[1], done: false };
                case 5: _.label++; y = op[1]; op = [0]; continue;
                case 7: op = _.ops.pop(); _.trys.pop(); continue;
                default:
                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
                    if (t[2]) _.ops.pop();
                    _.trys.pop(); continue;
            }
            op = body.call(thisArg, _);
        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
    }
};
Object.defineProperty(exports, "__esModule", { value: true });
var types_pb_1 = require("./kkProto/types_pb");
var messages_pb_1 = require("./kkProto/messages_pb");
var exchange_pb_1 = require("./kkProto/exchange_pb");
var utils_1 = require("./utils");
var webUSBDevice_1 = require("./webUSBDevice");
var messageTypeRegistry_1 = require("./messageTypeRegistry");
var initialKeepKeyArgs = {
    autoButton: false,
    device: null
};
var KeepKey = /** @class */ (function () {
    function KeepKey(config) {
        this.autoButton = false;
        var mergedConfig = __assign({}, initialKeepKeyArgs, config);
        this.autoButton = mergedConfig.autoButton;
        this.device = mergedConfig.device;
    }
    KeepKey.withWebUSB = function (webUSBDeviceConfig) {
        return new KeepKey({ autoButton: false, device: new webUSBDevice_1.default(webUSBDeviceConfig) });
    };
    KeepKey.prototype.acknowledgeWithCharacter = function (character) {
        return __awaiter(this, void 0, void 0, function () {
            return __generator(this, function (_a) {
                return [2 /*return*/, this.acknowledgeWithCharacterProto(character, false, false)];
            });
        });
    };
    KeepKey.prototype.acknowledgeWithCharacterDelete = function () {
        return __awaiter(this, void 0, void 0, function () {
            return __generator(this, function (_a) {
                return [2 /*return*/, this.acknowledgeWithCharacterProto('', true, false)];
            });
        });
    };
    KeepKey.prototype.acknowledgeWithCharacterDone = function () {
        return __awaiter(this, void 0, void 0, function () {
            return __generator(this, function (_a) {
                return [2 /*return*/, this.acknowledgeWithCharacterProto('', false, true)];
            });
        });
    };
    KeepKey.prototype.acknowledgeWithCharacterProto = function (character, _delete, _done) {
        return __awaiter(this, void 0, void 0, function () {
            var characterAck, _a, typeEnum, response, responseObj;
            return __generator(this, function (_b) {
                switch (_b.label) {
                    case 0:
                        characterAck = new messages_pb_1.default.CharacterAck();
                        if (character !== '') {
                            characterAck.setCharacter(character);
                        }
                        else if (_delete) {
                            characterAck.setDelete(_delete);
                        }
                        else if (_done) {
                            characterAck.setDone(_done);
                        }
                        return [4 /*yield*/, this.device.exchange(messages_pb_1.default.MessageType.MESSAGETYPE_CHARACTERACK, characterAck)];
                    case 1:
                        _a = _b.sent(), typeEnum = _a[0], response = _a[1];
                        responseObj = response.toObject();
                        // Emit event to notify clients that a character has been exchanged
                        this.device.events.emit('CHARACTERACK_INTERRUPT_RESULT', typeEnum, response);
                        return [2 /*return*/, [typeEnum, responseObj]];
                }
            });
        });
    };
    // Send passphrase to the device, this will typically be called in response to a MESSAGETYPE_PASSPHRASEREQUEST event
    KeepKey.prototype.acknowledgeWithPassphrase = function (passphrase) {
        return __awaiter(this, void 0, void 0, function () {
            var passphraseAck, _a, typeEnum, response, responseObj;
            return __generator(this, function (_b) {
                switch (_b.label) {
                    case 0:
                        passphraseAck = new messages_pb_1.default.PassphraseAck();
                        passphraseAck.setPassphrase(passphrase);
                        return [4 /*yield*/, this.device.exchange(messages_pb_1.default.MessageType.MESSAGETYPE_PASSPHRASEACK, passphraseAck)];
                    case 1:
                        _a = _b.sent(), typeEnum = _a[0], response = _a[1];
                        responseObj = response.toObject();
                        // Emit event to notify clients that passphrase has been exchanged
                        this.device.events.emit('PASSPHRASEACK_INTERRUPT_RESULT', typeEnum, response);
                        return [2 /*return*/, [typeEnum, responseObj]];
                }
            });
        });
    };
    // Send pin to the device, this will typically be called in response to a MESSAGETYPE_PINMATRIXREQUEST event
    KeepKey.prototype.acknowledgeWithPin = function (pin) {
        return __awaiter(this, void 0, void 0, function () {
            var matrixAck, _a, typeEnum, response, responseObj;
            return __generator(this, function (_b) {
                switch (_b.label) {
                    case 0:
                        matrixAck = new messages_pb_1.default.PinMatrixAck();
                        matrixAck.setPin(pin);
                        return [4 /*yield*/, this.device.exchange(messages_pb_1.default.MessageType.MESSAGETYPE_PINMATRIXACK, matrixAck)];
                    case 1:
                        _a = _b.sent(), typeEnum = _a[0], response = _a[1];
                        responseObj = response.toObject();
                        // Emit event to notify clients that pin has been exchanged
                        this.device.events.emit('PINMATRIXACK_INTERRUPT_RESULT', typeEnum, response);
                        return [2 /*return*/, [typeEnum, responseObj]];
                }
            });
        });
    };
    // ApplyPolicy enables or disables a named policy such as "ShapeShift" on the device
    KeepKey.prototype.applyPolicy = function (p) {
        return __awaiter(this, void 0, void 0, function () {
            var policy, applyPolicies;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        policy = new types_pb_1.default.PolicyType();
                        policy.setPolicyName(p.policyName);
                        policy.setEnabled(p.enabled);
                        applyPolicies = new messages_pb_1.default.ApplyPolicies();
                        applyPolicies.setPolicyList([policy]);
                        return [4 /*yield*/, this.device.exchange(messages_pb_1.default.MessageType.MESSAGETYPE_APPLYPOLICIES, applyPolicies)];
                    case 1:
                        _a.sent();
                        return [2 /*return*/];
                }
            });
        });
    };
    // ApplySettings changes the label, language, and enabling/disabling the passphrase
    // The default language is english
    KeepKey.prototype.applySettings = function (s) {
        return __awaiter(this, void 0, void 0, function () {
            var applySettings;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        applySettings = new messages_pb_1.default.ApplySettings();
                        if (s.label) {
                            applySettings.setLabel(s.label);
                        }
                        if (s.language) {
                            applySettings.setLanguage(s.language);
                        }
                        if (s.usePassphrase !== undefined) {
                            applySettings.setUsePassphrase(s.usePassphrase);
                        }
                        if (s.autoLockDelayMs) {
                            applySettings.setAutoLockDelayMs(s.autoLockDelayMs);
                        }
                        if (s.u2fCounter) {
                            applySettings.setU2fCounter(s.u2fCounter);
                        }
                        return [4 /*yield*/, this.device.exchange(messages_pb_1.default.MessageType.MESSAGETYPE_APPLYSETTINGS, applySettings)];
                    case 1:
                        _a.sent();
                        return [2 /*return*/];
                }
            });
        });
    };
    // Cancel aborts the last device action that required user interaction
    // It can follow a button request, passphrase request, or pin request
    KeepKey.prototype.cancel = function () {
        return __awaiter(this, void 0, void 0, function () {
            var cancel;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        cancel = new messages_pb_1.default.Cancel();
                        // send
                        return [4 /*yield*/, this.device.exchange(messages_pb_1.default.MessageType.MESSAGETYPE_CANCEL, cancel)
                            // Emit event to notify clients that an action has been cancelled
                        ];
                    case 1:
                        // send
                        _a.sent();
                        // Emit event to notify clients that an action has been cancelled
                        this.device.events.emit('CANCEL_ACTION');
                        return [2 /*return*/];
                }
            });
        });
    };
    // ChangePin requests setting/changing the pin
    KeepKey.prototype.changePin = function () {
        return __awaiter(this, void 0, void 0, function () {
            var changePin;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        changePin = new messages_pb_1.default.ChangePin();
                        // User may be propmpted for button press up to 2 times
                        return [4 /*yield*/, this.device.exchange(messages_pb_1.default.MessageType.MESSAGETYPE_CHANGEPIN, changePin)];
                    case 1:
                        // User may be propmpted for button press up to 2 times
                        _a.sent();
                        return [2 /*return*/];
                }
            });
        });
    };
    // CipherKeyValue encrypts or decrypts a value with a given key, nodepath, and initializationVector
    // This method encrypts if encrypt is true and decrypts if false, the confirm paramater determines wether
    // the user is prompted on the device. See EncryptKeyValue() and DecryptKeyValue() for convenience methods
    // NOTE: If the length of the value in bytes is not divisible by 16 it will be zero padded
    KeepKey.prototype.cipherKeyValue = function (v) {
        return __awaiter(this, void 0, void 0, function () {
            var cipherKeyValue, _a, _, response, value;
            return __generator(this, function (_b) {
                switch (_b.label) {
                    case 0:
                        cipherKeyValue = new messages_pb_1.default.CipherKeyValue();
                        cipherKeyValue.setAddressNList(v.addressNList);
                        cipherKeyValue.setKey(v.key);
                        cipherKeyValue.setValue(v.value);
                        cipherKeyValue.setEncrypt(v.encrypt);
                        cipherKeyValue.setAskOnEncrypt(v.askOnEncrypt || false);
                        cipherKeyValue.setAskOnDecrypt(v.askOnDecrypt || false);
                        cipherKeyValue.setIv(v.iv || '');
                        return [4 /*yield*/, this.device.exchange(messages_pb_1.default.MessageType.MESSAGETYPE_CIPHERKEYVALUE, cipherKeyValue)];
                    case 1:
                        _a = _b.sent(), _ = _a[0], response = _a[1];
                        value = response.toObject().value;
                        return [2 /*return*/, value];
                }
            });
        });
    };
    // ClearSession clears cached session values such as the pin and passphrase
    KeepKey.prototype.clearSession = function () {
        return __awaiter(this, void 0, void 0, function () {
            var clearSession;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        clearSession = new messages_pb_1.default.ClearSession();
                        return [4 /*yield*/, this.device.exchange(messages_pb_1.default.MessageType.MESSAGETYPE_CLEARSESSION, clearSession)];
                    case 1:
                        _a.sent();
                        return [2 /*return*/];
                }
            });
        });
    };
    // DecryptKeyValue is a convenience method around decrypting with CipherKeyValue().
    // For more granular control of the process use CipherKeyValue()
    KeepKey.prototype.decryptKeyValue = function (v) {
        return __awaiter(this, void 0, void 0, function () {
            return __generator(this, function (_a) {
                return [2 /*return*/, this.cipherKeyValue(v)];
            });
        });
    };
    // EthereumGetAddress returns the ethereum address associated with the given node path
    // Optionally you can display  the address on the screen
    KeepKey.prototype.ethereumGetAddress = function (a) {
        return __awaiter(this, void 0, void 0, function () {
            var getAddr, _a, _, response, ethAddress;
            return __generator(this, function (_b) {
                switch (_b.label) {
                    case 0:
                        getAddr = new messages_pb_1.default.EthereumGetAddress();
                        getAddr.setAddressNList(a.addressNList);
                        getAddr.setShowDisplay(a.showDisplay !== false);
                        return [4 /*yield*/, this.device.exchange(messages_pb_1.default.MessageType.MESSAGETYPE_ETHEREUMGETADDRESS, getAddr)];
                    case 1:
                        _a = _b.sent(), _ = _a[0], response = _a[1];
                        ethAddress = response;
                        if (ethAddress.hasAddressStr()) {
                            return [2 /*return*/, ethAddress.getAddressStr()];
                        }
                        else if (ethAddress.hasAddress()) {
                            return [2 /*return*/, '0x' + utils_1.toHexString(ethAddress.getAddress_asU8())];
                        }
                        throw new Error('unable to obtain eth address from device');
                }
            });
        });
    };
    // Sign an ethereum transaction using a given node path
    // The user may be prompted for a pin and/or passphrase if they are enabled
    KeepKey.prototype.ethereumSignTx = function (tx, addressType, exchangeType, data, chainId) {
        return __awaiter(this, void 0, void 0, function () {
            var est, dataChunk, dataRemaining, response, nextResponse, dataLength;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        est = new messages_pb_1.default.EthereumSignTx();
                        if (addressType === types_pb_1.default.OutputAddressType.TRANSFER) {
                            throw Error('Not implemented yet.');
                        }
                        else if (addressType === types_pb_1.default.OutputAddressType.EXCHANGE) {
                            est.setAddressNList(tx.addressNList);
                            est.setNonce(typeof tx.nonce === 'string' ? utils_1.arrayify(tx.nonce) : tx.nonce);
                            est.setGasPrice(typeof tx.gasPrice === 'string' ? utils_1.arrayify(tx.gasPrice) : tx.gasPrice);
                            est.setGasLimit(typeof tx.gasLimit === 'string' ? utils_1.arrayify(tx.gasLimit) : tx.gasLimit);
                            est.setValue(typeof tx.value === 'string' ? utils_1.arrayify(tx.value) : tx.value);
                            est.setAddressType(types_pb_1.default.OutputAddressType.EXCHANGE);
                            est.setExchangeType(exchangeType);
                        }
                        else {
                            est.setAddressNList(tx.addressNList);
                            est.setNonce(typeof tx.nonce === 'string' ? utils_1.arrayify(tx.nonce) : tx.nonce);
                            est.setGasPrice(typeof tx.gasPrice === 'string' ? utils_1.arrayify(tx.gasPrice) : tx.gasPrice);
                            est.setGasLimit(typeof tx.gasLimit === 'string' ? utils_1.arrayify(tx.gasLimit) : tx.gasLimit);
                            est.setValue(typeof tx.value === 'string' ? utils_1.arrayify(tx.value) : tx.value);
                            est.setAddressType(types_pb_1.default.OutputAddressType.SPEND);
                        }
                        if (tx.to) {
                            if (typeof tx.to === 'string')
                                est.setTo(utils_1.arrayify(tx.to));
                            else
                                est.setTo(tx.to);
                        }
                        dataChunk = null;
                        dataRemaining = typeof data === 'string' ? utils_1.arrayify(data) : data;
                        if (dataRemaining) {
                            est.setDataLength(dataRemaining.length);
                            dataChunk = dataRemaining.slice(0, 1024);
                            dataRemaining = dataRemaining.slice(dataChunk.length);
                            est.setDataInitialChunk(dataChunk);
                        }
                        if (chainId != null) {
                            est.setChainId(chainId);
                        }
                        return [4 /*yield*/, this.device.exchange(messages_pb_1.default.MessageType.MESSAGETYPE_ETHEREUMSIGNTX, est)];
                    case 1:
                        nextResponse = _a.sent();
                        response = nextResponse[1];
                        _a.label = 2;
                    case 2:
                        if (!response.hasDataLength()) return [3 /*break*/, 4];
                        dataLength = response.getDataLength();
                        dataChunk = dataRemaining.slice(0, dataLength);
                        dataRemaining = dataRemaining.slice(dataLength, dataRemaining.length);
                        return [4 /*yield*/, this.device.exchange(messages_pb_1.default.MessageType.MESSAGETYPE_ETHEREUMSIGNTX, est)];
                    case 3:
                        nextResponse = _a.sent();
                        response = nextResponse[1];
                        return [3 /*break*/, 2];
                    case 4: return [2 /*return*/, {
                            r: '0x' + utils_1.toHexString(response.getSignatureR_asU8()),
                            s: '0x' + utils_1.toHexString(response.getSignatureS_asU8()),
                            v: '0x' + response.getSignatureV().toString(16)
                        }];
                }
            });
        });
    };
    KeepKey.prototype.ethereumSignMessage = function (m) {
        return __awaiter(this, void 0, void 0, function () {
            var msg, _a, _, response, sig;
            return __generator(this, function (_b) {
                switch (_b.label) {
                    case 0:
                        msg = new messages_pb_1.default.EthereumSignMessage();
                        msg.setAddressNList(m.addressNList || utils_1.bip32ToAddressNList("m/44'/60'/0'/0/0"));
                        msg.setMessage(m.message);
                        return [4 /*yield*/, this.device.exchange(messages_pb_1.default.MessageType.MESSAGETYPE_ETHEREUMSIGNMESSAGE, msg)];
                    case 1:
                        _a = _b.sent(), _ = _a[0], response = _a[1];
                        sig = response.toObject();
                        return [2 /*return*/, {
                                address: sig.address,
                                signature: sig.signature
                            }];
                }
            });
        });
    };
    KeepKey.prototype.ethereumVerifyMessage = function (m) {
        return __awaiter(this, void 0, void 0, function () {
            var msg, _a, _, response;
            return __generator(this, function (_b) {
                switch (_b.label) {
                    case 0:
                        msg = new messages_pb_1.default.EthereumVerifyMessage();
                        msg.setAddress(m.address);
                        msg.setSignature(m.signature);
                        msg.setMessage(m.message);
                        return [4 /*yield*/, this.device.exchange(messages_pb_1.default.MessageType.MESSAGETYPE_ETHEREUMVERIFYMESSAGE, msg)];
                    case 1:
                        _a = _b.sent(), _ = _a[0], response = _a[1];
                        return [2 /*return*/, typeof response === typeof messages_pb_1.default.Success];
                }
            });
        });
    };
    // FirmwareErase askes the device to erase its firmware
    KeepKey.prototype.firmwareErase = function () {
        return __awaiter(this, void 0, void 0, function () {
            var firmwareErase;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        firmwareErase = new messages_pb_1.default.FirmwareErase();
                        // send
                        return [4 /*yield*/, this.device.exchange(messages_pb_1.default.MessageType.MESSAGETYPE_FIRMWAREERASE, firmwareErase)];
                    case 1:
                        // send
                        _a.sent();
                        return [2 /*return*/];
                }
            });
        });
    };
    // Initialize assigns a hid connection to this KeepKey and send initialize message to device
    KeepKey.prototype.initialize = function () {
        return __awaiter(this, void 0, void 0, function () {
            var initialize, _a, _, response, features;
            return __generator(this, function (_b) {
                switch (_b.label) {
                    case 0: return [4 /*yield*/, this.device.initialize()
                        // send initialize
                    ];
                    case 1:
                        _b.sent();
                        initialize = new messages_pb_1.default.Initialize();
                        return [4 /*yield*/, this.device.exchange(messages_pb_1.default.MessageType.MESSAGETYPE_INITIALIZE, initialize)];
                    case 2:
                        _a = _b.sent(), _ = _a[0], response = _a[1];
                        features = response.toObject();
                        this.features = features;
                        return [2 /*return*/, features];
                }
            });
        });
    };
    // GetAddress returns an address string given a node path and a coin type.
    // Optionally you can display the address on the device screen
    // If passphrase is enabled this may request the passphrase.
    KeepKey.prototype.getAddress = function (g) {
        return __awaiter(this, void 0, void 0, function () {
            var address, _a, _, response, msg;
            return __generator(this, function (_b) {
                switch (_b.label) {
                    case 0:
                        address = new messages_pb_1.default.GetAddress();
                        address.setAddressNList(g.addressNList);
                        address.setCoinName(g.coinName);
                        address.setShowDisplay(g.showDisplay !== false);
                        address.setScriptType(g.scriptType || types_pb_1.default.InputScriptType.SPENDADDRESS);
                        return [4 /*yield*/, this.device.exchange(messages_pb_1.default.MessageType.MESSAGETYPE_GETADDRESS, address)];
                    case 1:
                        _a = _b.sent(), _ = _a[0], response = _a[1];
                        msg = response.toObject();
                        return [2 /*return*/, msg.address];
                }
            });
        });
    };
    // GetFeatures returns the features and other device information such as the version, label, and supported coins
    KeepKey.prototype.getFeatures = function () {
        return __awaiter(this, void 0, void 0, function () {
            var features, _a, _, response;
            return __generator(this, function (_b) {
                switch (_b.label) {
                    case 0:
                        features = new messages_pb_1.default.GetFeatures();
                        return [4 /*yield*/, this.device.exchange(messages_pb_1.default.MessageType.MESSAGETYPE_GETFEATURES, features)];
                    case 1:
                        _a = _b.sent(), _ = _a[0], response = _a[1];
                        return [2 /*return*/, response.toObject()];
                }
            });
        });
    };
    // GetEntropy requests sample data from the hardware RNG
    KeepKey.prototype.getEntropy = function (size) {
        return __awaiter(this, void 0, void 0, function () {
            var getEntropy, _a, _, response, entropy;
            return __generator(this, function (_b) {
                switch (_b.label) {
                    case 0:
                        getEntropy = new messages_pb_1.default.GetEntropy();
                        getEntropy.setSize(size);
                        return [4 /*yield*/, this.device.exchange(messages_pb_1.default.MessageType.MESSAGETYPE_GETENTROPY, getEntropy)];
                    case 1:
                        _a = _b.sent(), _ = _a[0], response = _a[1];
                        entropy = response.toObject().entropy;
                        return [2 /*return*/, entropy];
                }
            });
        });
    };
    // GetPublicKey asks the device for a public key corresponding to a nodePath and curve name.
    // Returns the hdnode, the XPUB as a string and a possidble error
    // This may prompt the user for a passphrase
    KeepKey.prototype.getPublicKey = function (g) {
        return __awaiter(this, void 0, void 0, function () {
            var getPublicKey, _a, _, response, publicKey;
            return __generator(this, function (_b) {
                switch (_b.label) {
                    case 0:
                        getPublicKey = new messages_pb_1.default.GetPublicKey();
                        getPublicKey.setAddressNList(g.addressNList);
                        getPublicKey.setEcdsaCurveName(g.ecdsaCurveName || 'secp256k1');
                        getPublicKey.setShowDisplay(g.showDisplay || false);
                        getPublicKey.setScriptType(g.scriptType || types_pb_1.default.InputScriptType.SPENDADDRESS);
                        return [4 /*yield*/, this.device.exchange(messages_pb_1.default.MessageType.MESSAGETYPE_GETPUBLICKEY, getPublicKey)];
                    case 1:
                        _a = _b.sent(), _ = _a[0], response = _a[1];
                        publicKey = response.toObject();
                        return [2 /*return*/, [publicKey.node, publicKey.xpub]];
                }
            });
        });
    };
    // GetNumCoins returns the number of coins supported by the device regardless of if the hanve funds.
    KeepKey.prototype.getNumCoins = function () {
        return __awaiter(this, void 0, void 0, function () {
            var getCoinTable, _a, _, response;
            return __generator(this, function (_b) {
                switch (_b.label) {
                    case 0:
                        getCoinTable = new messages_pb_1.default.GetCoinTable();
                        return [4 /*yield*/, this.device.exchange(messages_pb_1.default.MessageType.MESSAGETYPE_GETCOINTABLE, getCoinTable)];
                    case 1:
                        _a = _b.sent(), _ = _a[0], response = _a[1];
                        return [2 /*return*/, response.getNumCoins()];
                }
            });
        });
    };
    KeepKey.prototype.getAllCoinsAsMap = function () {
        return __awaiter(this, void 0, void 0, function () {
            var numCoins, coinTable, i, pagedTable;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4 /*yield*/, this.getNumCoins()];
                    case 1:
                        numCoins = _a.sent();
                        coinTable = {};
                        i = 0;
                        _a.label = 2;
                    case 2:
                        if (!(i < numCoins)) return [3 /*break*/, 5];
                        return [4 /*yield*/, this.getCoinTable(i, i + Math.min(numCoins - i, 10))];
                    case 3:
                        pagedTable = _a.sent();
                        pagedTable.filter(function (coin) { return !coin.coinShortcut.startsWith(' '); }).forEach(function (coinType) {
                            var symbol = coinType.coinShortcut;
                            coinTable[symbol] = {
                                coinShortcut: symbol,
                                bip44AccountPath: coinType.bip44AccountPath,
                                curveName: coinType.curveName,
                                coinName: coinType.coinName
                            };
                        });
                        _a.label = 4;
                    case 4:
                        i += 10;
                        return [3 /*break*/, 2];
                    case 5: return [2 /*return*/, coinTable];
                }
            });
        });
    };
    // GetCoinTable returns an array of Types.CoinTypes, with start and end arguments for paging.
    // You cannot request more than 10 at a time.
    KeepKey.prototype.getCoinTable = function (start, end) {
        if (start === void 0) { start = 0; }
        if (end === void 0) { end = start + 10; }
        return __awaiter(this, void 0, void 0, function () {
            var getCoinTable, _a, _, response, coinTable;
            return __generator(this, function (_b) {
                switch (_b.label) {
                    case 0:
                        getCoinTable = new messages_pb_1.default.GetCoinTable();
                        getCoinTable.setStart(start);
                        getCoinTable.setEnd(end);
                        return [4 /*yield*/, this.device.exchange(messages_pb_1.default.MessageType.MESSAGETYPE_GETCOINTABLE, getCoinTable)];
                    case 1:
                        _a = _b.sent(), _ = _a[0], response = _a[1];
                        coinTable = response.toObject();
                        return [2 /*return*/, coinTable.tableList];
                }
            });
        });
    };
    // getCoinShortcutXPubPairs returns an array of [coinShortcut, xPub] pairs
    KeepKey.prototype.getCoinShortcutXPubPairs = function (coinTable) {
        return __awaiter(this, void 0, void 0, function () {
            var publicKeys, pairs;
            var _this = this;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4 /*yield*/, Promise.all(coinTable.map(function (coinType) { return _this.getPublicKey({
                            addressNList: [2147483648 + 44, coinType.bip44AccountPath, 2147483648]
                        }); }))];
                    case 1:
                        publicKeys = _a.sent();
                        pairs = [];
                        publicKeys.forEach(function (_a, i) {
                            var xPub = _a[1];
                            pairs.push([coinTable[i].coinShortcut, xPub]);
                        });
                        return [2 /*return*/, pairs];
                }
            });
        });
    };
    // LoadDevice loads a provided seed onto the device and applies the provided settings
    // including setting a pin/device label, enabling/disabling the passphrase, and whether to
    // check the checksum of the provided mnemonic
    KeepKey.prototype.loadDevice = function (l) {
        return __awaiter(this, void 0, void 0, function () {
            var loadDevice;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        loadDevice = new messages_pb_1.default.LoadDevice();
                        loadDevice.setMnemonic(l.mnemonic);
                        loadDevice.setPassphraseProtection(l.passphraseProtection || false);
                        loadDevice.setSkipChecksum(l.skipChecksum || true);
                        if (l.pin)
                            loadDevice.setPin(l.pin);
                        if (l.label)
                            loadDevice.setLabel(l.label);
                        // send
                        return [4 /*yield*/, this.device.exchange(messages_pb_1.default.MessageType.MESSAGETYPE_LOADDEVICE, loadDevice)];
                    case 1:
                        // send
                        _a.sent();
                        return [2 /*return*/];
                }
            });
        });
    };
    KeepKey.prototype.recoveryDevice = function (r) {
        return __awaiter(this, void 0, void 0, function () {
            var msg, epoch;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        if (r.wordCount !== 12 && r.wordCount !== 18 && r.wordCount !== 24) {
                            throw new Error('Invalid word count. Use 12/18/24');
                        }
                        msg = new messages_pb_1.default.RecoveryDevice();
                        msg.setWordCount(r.wordCount);
                        msg.setPassphraseProtection(r.passphraseProtection);
                        msg.setPinProtection(r.pinProtection);
                        msg.setLabel(r.label);
                        msg.setLanguage(r.language || 'english');
                        msg.setEnforceWordlist(true);
                        msg.setUseCharacterCipher(true);
                        if (r.autoLockDelayMs) {
                            msg.setAutoLockDelayMs(r.autoLockDelayMs);
                        }
                        epoch = Math.floor(+new Date() / 1000);
                        msg.setU2fCounter(r.u2fCounter || epoch);
                        return [4 /*yield*/, this.device.exchange(messages_pb_1.default.MessageType.MESSAGETYPE_RECOVERYDEVICE, msg)];
                    case 1:
                        _a.sent();
                        return [2 /*return*/];
                }
            });
        });
    };
    // Ping the device. If a message is provided it will be shown on the device screen and returned
    // in the success message. Optionally require a button press, pin, or passphrase to continue
    KeepKey.prototype.ping = function (p) {
        return __awaiter(this, void 0, void 0, function () {
            var ping, _a, _, response, message;
            return __generator(this, function (_b) {
                switch (_b.label) {
                    case 0:
                        ping = new messages_pb_1.default.Ping();
                        ping.setMessage(p.message);
                        ping.setButtonProtection(p.buttonProtection || false);
                        ping.setPinProtection(p.pinProtection || false);
                        ping.setPassphraseProtection(p.passphraseProtection || false);
                        return [4 /*yield*/, this.device.exchange(messages_pb_1.default.MessageType.MESSAGETYPE_PING, ping)];
                    case 1:
                        _a = _b.sent(), _ = _a[0], response = _a[1];
                        message = response.toObject().message;
                        return [2 /*return*/, message];
                }
            });
        });
    };
    KeepKey.prototype.prepareSignTx = function (coinName, inputs, outputs, exchangeOutputs) {
        return __awaiter(this, void 0, void 0, function () {
            var txmap, unsignedTx;
            return __generator(this, function (_a) {
                txmap = {} // Create a map of transactions by txid needed for the KeepKey signing flow.
                ;
                unsignedTx = new types_pb_1.default.TransactionType();
                unsignedTx.setVersion(2);
                unsignedTx.setInputsCnt(inputs.length);
                unsignedTx.setOutputsCnt(outputs.length);
                unsignedTx.setLockTime(0); // TODO: remove?
                inputs.forEach(function (input, i) {
                    var utxo = new types_pb_1.default.TxInputType();
                    utxo.setPrevHash(utils_1.fromHexString(input.txid));
                    utxo.setPrevIndex(input.vout);
                    // utxo.setSequence(4294967295)  // TODO: check this
                    // utxo.setScriptType(Types.InputScriptType.SPENDADDRESS)  // TODO: handle multisig & segwit
                    utxo.setAddressNList(input.address_n); // bip-32 path to the master key.  TODO: check this
                    utxo.setAmount(input.amount); // Only required by KeepKey for segwit inputs
                    unsignedTx.addInputs(utxo, i);
                });
                outputs.forEach(function (output, k) {
                    var newOutput = new types_pb_1.default.TxOutputType();
                    newOutput.setAmount(output.amount);
                    newOutput.setScriptType(types_pb_1.default.OutputScriptType.PAYTOADDRESS); // TODO: Support all script types. NOTE: Older firmware may require PAYTOSCRIPTHASH.
                    if (exchangeOutputs && exchangeOutputs[k]) {
                        var exchangeOutput = exchangeOutputs[k];
                        // convert the base64 encoded signedExchangeResponse message into the correct object
                        var signedExchange = exchange_pb_1.default.SignedExchangeResponse.deserializeBinary(exchangeOutput.signed_exchange_response);
                        // decode the deposit amount from a little-endian Uint8Array into an unsigned uint64
                        var depAmt = signedExchange.getResponsev2().getDepositAmount_asU8();
                        var val = 0;
                        for (var jj = depAmt.length - 1; jj >= 0; jj--) {
                            val += depAmt[jj] * Math.pow(2, (8 * (depAmt.length - jj - 1)));
                            // TODO validate is uint64
                        }
                        var outExchangeType = new types_pb_1.default.ExchangeType();
                        outExchangeType.setSignedExchangeResponse(signedExchange);
                        outExchangeType.setWithdrawalCoinName(exchangeOutput.withdrawal_coin_name);
                        outExchangeType.setWithdrawalAddressNList(exchangeOutput.withdrawal_address_n);
                        outExchangeType.setReturnAddressNList(exchangeOutput.return_address_n);
                        newOutput.setAmount(val);
                        newOutput.setAddress(signedExchange.toObject().responsev2.depositAddress.address);
                        newOutput.setScriptType(types_pb_1.default.OutputScriptType.PAYTOADDRESS);
                        newOutput.setAddressType(3);
                        newOutput.setExchangeType(outExchangeType);
                    }
                    else if (output.isChange) {
                        newOutput.setAddressNList(output.address_n);
                        newOutput.setAddressType(types_pb_1.default.OutputAddressType.CHANGE);
                    }
                    else {
                        newOutput.setAddress(output.address);
                        newOutput.setAddressType(types_pb_1.default.OutputAddressType.SPEND);
                    }
                    unsignedTx.addOutputs(newOutput, k);
                });
                txmap['unsigned'] = unsignedTx;
                inputs.forEach(function (inputTx) {
                    var tx = new types_pb_1.default.TransactionType();
                    tx.setVersion(inputTx.tx.version);
                    tx.setLockTime(inputTx.tx.locktime); // TODO: remove?
                    tx.setInputsCnt(inputTx.tx.vin.length);
                    tx.setOutputsCnt(inputTx.tx.vout.length);
                    inputTx.tx.vin.forEach(function (vin, i) {
                        var txInput = new types_pb_1.default.TxInputType();
                        txInput.setPrevHash(utils_1.fromHexString(vin.txid));
                        txInput.setPrevIndex(vin.vout);
                        txInput.setSequence(vin.sequence);
                        txInput.setScriptSig(utils_1.fromHexString(vin.scriptSig.hex));
                        txInput.setScriptType(types_pb_1.default.InputScriptType.SPENDADDRESS);
                        txInput.setAmount(vin.valueSat);
                        tx.addInputs(txInput, i);
                    });
                    inputTx.tx.vout.forEach(function (vout, i) {
                        var txOutput = new types_pb_1.default.TxOutputBinType();
                        txOutput.setAmount(Number((vout.value * (Math.pow(10, 8))).toFixed(0)));
                        txOutput.setScriptPubkey(utils_1.fromHexString(vout.scriptPubKey.hex));
                        tx.addBinOutputs(txOutput, i);
                    });
                    txmap[inputTx.txid] = tx;
                });
                return [2 /*return*/, txmap];
            });
        });
    };
    // RemovePin disables pin protection for the device. If a pin is currently enabled
    // it will prompt the user to enter the current pin
    KeepKey.prototype.removePin = function () {
        return __awaiter(this, void 0, void 0, function () {
            var changePin;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        changePin = new messages_pb_1.default.ChangePin();
                        changePin.setRemove(true);
                        // send
                        return [4 /*yield*/, this.device.exchange(messages_pb_1.default.MessageType.MESSAGETYPE_CHANGEPIN, changePin)];
                    case 1:
                        // send
                        _a.sent();
                        return [2 /*return*/];
                }
            });
        });
    };
    // ResetDevice generates a new seed using device RNG for entropy and applies the provided settings
    // The device must be uninitialized  before calling this method. This can be achieved by calling WipeDevice()
    // The device entropy strength must be 128, 192, or 256
    KeepKey.prototype.resetDevice = function (r) {
        return __awaiter(this, void 0, void 0, function () {
            var resetDevice, epoch;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        resetDevice = new messages_pb_1.default.ResetDevice();
                        resetDevice.setStrength(r.strength || 128);
                        resetDevice.setDisplayRandom(r.displayRandom || false);
                        resetDevice.setPassphraseProtection(r.passphraseProtection || false);
                        resetDevice.setPinProtection(r.pinProtection || false);
                        resetDevice.setLabel(r.label);
                        if (r.autoLockDelayMs) {
                            resetDevice.setAutoLockDelayMs(r.autoLockDelayMs);
                        }
                        epoch = Math.floor(+new Date() / 1000);
                        resetDevice.setU2fCounter(r.u2fCounter || epoch);
                        // resetDevice.setWordsPerGape(wordsPerScreen) // Re-enable when patch gets in
                        // Send
                        return [4 /*yield*/, this.device.exchange(messages_pb_1.default.MessageType.MESSAGETYPE_RESETDEVICE, resetDevice)];
                    case 1:
                        // resetDevice.setWordsPerGape(wordsPerScreen) // Re-enable when patch gets in
                        // Send
                        _a.sent();
                        return [2 /*return*/];
                }
            });
        });
    };
    KeepKey.prototype.send = function (events) {
        return __awaiter(this, void 0, void 0, function () {
            var _loop_1, this_1, _i, events_1, event_1;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        _loop_1 = function (event_1) {
                            var MessageType, msg;
                            return __generator(this, function (_a) {
                                switch (_a.label) {
                                    case 0:
                                        MessageType = messageTypeRegistry_1.default[event_1.message_enum];
                                        msg = new MessageType();
                                        Object.entries(event_1.message).forEach(function (_a) {
                                            var key = _a[0], value = _a[1];
                                            var setterMethod = utils_1.protoFieldToSetMethod(key);
                                            if (msg[setterMethod]) {
                                                // Assume setter methods are always of the format: strength -> setStrength
                                                // until this exists https://github.com/protocolbuffers/protobuf/issues/1591
                                                msg[setterMethod](value);
                                            }
                                        });
                                        return [4 /*yield*/, this_1.device.exchange(event_1.message_enum, msg)];
                                    case 1:
                                        _a.sent();
                                        return [2 /*return*/];
                                }
                            });
                        };
                        this_1 = this;
                        _i = 0, events_1 = events;
                        _a.label = 1;
                    case 1:
                        if (!(_i < events_1.length)) return [3 /*break*/, 4];
                        event_1 = events_1[_i];
                        return [5 /*yield**/, _loop_1(event_1)];
                    case 2:
                        _a.sent();
                        _a.label = 3;
                    case 3:
                        _i++;
                        return [3 /*break*/, 1];
                    case 4: return [2 /*return*/];
                }
            });
        });
    };
    // Sign UTXO Transaction
    KeepKey.prototype.signTransaction = function (coinName, inputs, outputs, exchangeOutputs, version, lockTime) {
        if (exchangeOutputs === void 0) { exchangeOutputs = []; }
        return __awaiter(this, void 0, void 0, function () {
            var _a, txmap, tx, responseType, response, signatures, serializedTx, messageCount, errorResponse, txRequest, currentTx, msg, txAck, nextResponse, nextResponse, nextResponse, offset, length_1, nextResponse;
            return __generator(this, function (_b) {
                switch (_b.label) {
                    case 0: return [4 /*yield*/, this.prepareSignTx(coinName, inputs, outputs, exchangeOutputs)
                        // Prepare and send initial message
                    ];
                    case 1:
                        txmap = _b.sent();
                        tx = new messages_pb_1.default.SignTx();
                        tx.setInputsCount(inputs.length);
                        tx.setOutputsCount(outputs.length);
                        tx.setCoinName(coinName);
                        if (version != null)
                            tx.setVersion(version);
                        if (lockTime != null)
                            tx.setLockTime(lockTime);
                        return [4 /*yield*/, this.device.exchange(messages_pb_1.default.MessageType.MESSAGETYPE_SIGNTX, tx)
                            // Prepare structure for signatures
                        ];
                    case 2:
                        _a = _b.sent(), responseType = _a[0], response = _a[1];
                        signatures = new Array(inputs.length).fill(null);
                        serializedTx = '';
                        messageCount = 0;
                        _b.label = 3;
                    case 3:
                        if (!true) return [3 /*break*/, 12];
                        messageCount += 1;
                        if (responseType === messages_pb_1.default.MessageType.MESSAGETYPE_FAILURE) {
                            errorResponse = response;
                            throw new Error("Signing failed: " + errorResponse.getMessage());
                        }
                        if (responseType !== messages_pb_1.default.MessageType.MESSAGETYPE_TXREQUEST) {
                            throw new Error("Unexpected message type: " + responseType);
                        }
                        txRequest = response;
                        // If there's some part of signed transaction, add it
                        if (txRequest.hasSerialized() && txRequest.getSerialized().hasSerializedTx()) {
                            serializedTx += utils_1.toHexString(txRequest.getSerialized().getSerializedTx_asU8());
                        }
                        if (txRequest.hasSerialized() && txRequest.getSerialized().hasSignatureIndex()) {
                            if (signatures[txRequest.getSerialized().getSignatureIndex()] !== null) {
                                throw new Error("Signature for index " + txRequest.getSerialized().getSignatureIndex() + " already filled");
                            }
                            signatures[txRequest.getSerialized().getSignatureIndex()] = txRequest.getSerialized().getSignature_asB64();
                        }
                        if (txRequest.getRequestType() === types_pb_1.default.RequestType.TXFINISHED) {
                            // Device didn't ask for more information, finish workflow
                            return [3 /*break*/, 12];
                        }
                        currentTx = null;
                        msg = null;
                        txAck = null;
                        // Device asked for one more information, let's process it.
                        if (txRequest.hasDetails() && !txRequest.getDetails().hasTxHash()) {
                            currentTx = txmap['unsigned'];
                        }
                        else {
                            currentTx = txmap[utils_1.toHexString(txRequest.getDetails().getTxHash_asU8())];
                        }
                        if (!(txRequest.getRequestType() === types_pb_1.default.RequestType.TXMETA)) return [3 /*break*/, 5];
                        msg = new types_pb_1.default.TransactionType();
                        msg.setVersion(currentTx.getVersion());
                        msg.setLockTime(currentTx.getLockTime());
                        msg.setInputsCnt(currentTx.getInputsCnt());
                        if (txRequest.getDetails().hasTxHash()) {
                            msg.setOutputsCnt(currentTx.getBinOutputsList().length);
                        }
                        else {
                            msg.setOutputsCnt(currentTx.getOutputsList().length);
                        }
                        if (currentTx.hasExtraData()) {
                            msg.setExtraDataLen(currentTx.getExtraData_asU8().length);
                        }
                        else {
                            msg.setExtraDataLen(0);
                        }
                        txAck = new messages_pb_1.default.TxAck();
                        txAck.setTx(msg);
                        return [4 /*yield*/, this.device.exchange(messages_pb_1.default.MessageType.MESSAGETYPE_TXACK, txAck)];
                    case 4:
                        nextResponse = _b.sent();
                        responseType = nextResponse[0];
                        response = nextResponse[1];
                        return [3 /*break*/, 11];
                    case 5:
                        if (!(txRequest.getRequestType() === types_pb_1.default.RequestType.TXINPUT)) return [3 /*break*/, 7];
                        msg = new types_pb_1.default.TransactionType();
                        msg.setInputsList([currentTx.getInputsList()[txRequest.getDetails().getRequestIndex()]]);
                        txAck = new messages_pb_1.default.TxAck();
                        txAck.setTx(msg);
                        return [4 /*yield*/, this.device.exchange(messages_pb_1.default.MessageType.MESSAGETYPE_TXACK, txAck)];
                    case 6:
                        nextResponse = _b.sent();
                        responseType = nextResponse[0];
                        response = nextResponse[1];
                        return [3 /*break*/, 11];
                    case 7:
                        if (!(txRequest.getRequestType() === types_pb_1.default.RequestType.TXOUTPUT)) return [3 /*break*/, 9];
                        msg = new types_pb_1.default.TransactionType();
                        if (txRequest.getDetails().hasTxHash()) {
                            msg.setBinOutputsList([currentTx.getBinOutputsList()[txRequest.getDetails().getRequestIndex()]]);
                        }
                        else {
                            msg.setOutputsList([currentTx.getOutputsList()[txRequest.getDetails().getRequestIndex()]]);
                            msg.setOutputsCnt(1);
                        }
                        txAck = new messages_pb_1.default.TxAck();
                        txAck.setTx(msg);
                        return [4 /*yield*/, this.device.exchange(messages_pb_1.default.MessageType.MESSAGETYPE_TXACK, txAck)];
                    case 8:
                        nextResponse = _b.sent();
                        responseType = nextResponse[0];
                        response = nextResponse[1];
                        return [3 /*break*/, 11];
                    case 9:
                        if (!(txRequest.getRequestType() === types_pb_1.default.RequestType.TXEXTRADATA)) return [3 /*break*/, 11];
                        offset = txRequest.getDetails().getExtraDataOffset();
                        length_1 = txRequest.getDetails().getExtraDataLen();
                        msg = new types_pb_1.default.TransactionType();
                        msg.setExtraData(currentTx.getExtraData_asU8().slice(offset, offset + length_1));
                        txAck = new messages_pb_1.default.TxAck();
                        txAck.setTx(msg);
                        return [4 /*yield*/, this.device.exchange(messages_pb_1.default.MessageType.MESSAGETYPE_TXACK, txAck)];
                    case 10:
                        nextResponse = _b.sent();
                        responseType = nextResponse[0];
                        response = nextResponse[1];
                        _b.label = 11;
                    case 11: return [3 /*break*/, 3];
                    case 12:
                        if (signatures.includes(null)) {
                            throw new Error('Some signatures are missing!');
                        }
                        return [2 /*return*/, [signatures, serializedTx]];
                }
            });
        });
    };
    // SignMessage signs a message using the given nodepath and Coin
    KeepKey.prototype.signMessage = function (s) {
        return __awaiter(this, void 0, void 0, function () {
            var sign, _a, _, response, messageSignature;
            return __generator(this, function (_b) {
                switch (_b.label) {
                    case 0:
                        sign = new messages_pb_1.default.SignMessage();
                        sign.setAddressNList(s.addressNList);
                        sign.setMessage(s.message);
                        sign.setCoinName(s.coinName);
                        sign.setScriptType(s.scriptType || types_pb_1.default.InputScriptType.SPENDADDRESS);
                        return [4 /*yield*/, this.device.exchange(messages_pb_1.default.MessageType.MESSAGETYPE_SIGNMESSAGE, sign)];
                    case 1:
                        _a = _b.sent(), _ = _a[0], response = _a[1];
                        messageSignature = response.toObject();
                        return [2 /*return*/, [messageSignature.signature, messageSignature.address]];
                }
            });
        });
    };
    // SoftReset power cycles the device. The device only responds to
    // this message while in manufacturer mode
    KeepKey.prototype.softReset = function () {
        return __awaiter(this, void 0, void 0, function () {
            var softReset;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        softReset = new messages_pb_1.default.SoftReset();
                        // send
                        return [4 /*yield*/, this.device.exchange(messages_pb_1.default.MessageType.MESSAGETYPE_SOFTRESET, softReset)];
                    case 1:
                        // send
                        _a.sent();
                        return [2 /*return*/];
                }
            });
        });
    };
    // VerifyMessage verifies a signed message
    KeepKey.prototype.verifyMessage = function (addr, coinName, msg, sig) {
        return __awaiter(this, void 0, void 0, function () {
            var verify;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        verify = new messages_pb_1.default.VerifyMessage();
                        verify.setAddress(addr);
                        verify.setSignature(sig);
                        verify.setMessage(msg);
                        verify.setCoinName(coinName);
                        // send
                        return [4 /*yield*/, this.device.exchange(messages_pb_1.default.MessageType.MESSAGETYPE_VERIFYMESSAGE, verify)];
                    case 1:
                        // send
                        _a.sent();
                        return [2 /*return*/];
                }
            });
        });
    };
    // WipeDevice wipes all sensitive data and settings
    KeepKey.prototype.wipeDevice = function () {
        return __awaiter(this, void 0, void 0, function () {
            var wipeDevice;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        wipeDevice = new messages_pb_1.default.WipeDevice();
                        // send
                        return [4 /*yield*/, this.device.exchange(messages_pb_1.default.MessageType.MESSAGETYPE_WIPEDEVICE, wipeDevice)];
                    case 1:
                        // send
                        _a.sent();
                        return [2 /*return*/];
                }
            });
        });
    };
    return KeepKey;
}());
exports.default = KeepKey;
//# sourceMappingURL=keepkey.js.map